diff options
author | Ben Chang <benc@nvidia.com> | 2017-06-24 12:14:22 +0000 |
---|---|---|
committer | Luca Barbato <lu_zero@gentoo.org> | 2017-06-24 12:35:46 +0000 |
commit | 2e8d88ad5281ab923e1d9772eb99fdfb483435c2 (patch) | |
tree | 08e2dc0a05ab98bc39eddf3a4941f79ed988e7e7 | |
parent | bb65eb62991e5165b9fad2702a8954a1fe3c6f1f (diff) | |
download | ffmpeg-2e8d88ad5281ab923e1d9772eb99fdfb483435c2.tar.gz |
nvenc: Use a fifo to manage the free surface pool
Previously, if a session allocates x surfaces, only x-1 surfaces are
used (due to combination of output delay and lock toggle logic).
-rw-r--r-- | libavcodec/nvenc.c | 23 | ||||
-rw-r--r-- | libavcodec/nvenc.h | 3 |
2 files changed, 15 insertions, 11 deletions
diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c index f16e509df3..7b30ad768e 100644 --- a/libavcodec/nvenc.c +++ b/libavcodec/nvenc.c @@ -986,6 +986,7 @@ static int nvenc_alloc_surface(AVCodecContext *avctx, int idx) { NVENCContext *ctx = avctx->priv_data; NV_ENCODE_API_FUNCTION_LIST *nv = &ctx->nvel.nvenc_funcs; + NVENCFrame *tmp_surface = &ctx->frames[idx]; int ret; NV_ENC_CREATE_BITSTREAM_BUFFER out_buffer = { 0 }; @@ -1046,6 +1047,8 @@ static int nvenc_alloc_surface(AVCodecContext *avctx, int idx) ctx->frames[idx].out = out_buffer.bitstreamBuffer; + av_fifo_generic_write(ctx->unused_surface_queue, &tmp_surface, sizeof(tmp_surface), NULL); + return 0; } @@ -1066,6 +1069,9 @@ static int nvenc_setup_surfaces(AVCodecContext *avctx) ctx->timestamps = av_fifo_alloc(ctx->nb_surfaces * sizeof(int64_t)); if (!ctx->timestamps) return AVERROR(ENOMEM); + ctx->unused_surface_queue = av_fifo_alloc(ctx->nb_surfaces * sizeof(NVENCFrame*)); + if (!ctx->unused_surface_queue) + return AVERROR(ENOMEM); ctx->pending = av_fifo_alloc(ctx->nb_surfaces * sizeof(*ctx->frames)); if (!ctx->pending) return AVERROR(ENOMEM); @@ -1123,6 +1129,7 @@ av_cold int ff_nvenc_encode_close(AVCodecContext *avctx) av_fifo_free(ctx->timestamps); av_fifo_free(ctx->pending); av_fifo_free(ctx->ready); + av_fifo_free(ctx->unused_surface_queue); if (ctx->frames) { for (i = 0; i < ctx->nb_surfaces; ++i) { @@ -1201,16 +1208,14 @@ av_cold int ff_nvenc_encode_init(AVCodecContext *avctx) static NVENCFrame *get_free_frame(NVENCContext *ctx) { - int i; + NVENCFrame *tmp_surf; - for (i = 0; i < ctx->nb_surfaces; i++) { - if (!ctx->frames[i].locked) { - ctx->frames[i].locked = 1; - return &ctx->frames[i]; - } - } + if (!(av_fifo_size(ctx->unused_surface_queue) > 0)) + // queue empty + return NULL; - return NULL; + av_fifo_generic_read(ctx->unused_surface_queue, &tmp_surf, sizeof(tmp_surf), NULL); + return tmp_surf; } static int nvenc_copy_frame(NV_ENC_LOCK_INPUT_BUFFER *in, const AVFrame *frame) @@ -1510,7 +1515,7 @@ static int nvenc_get_output(AVCodecContext *avctx, AVPacket *pkt) frame->in = NULL; } - frame->locked = 0; + av_fifo_generic_write(ctx->unused_surface_queue, &frame, sizeof(frame), NULL); ret = nvenc_set_timestamp(avctx, ¶ms, pkt); if (ret < 0) diff --git a/libavcodec/nvenc.h b/libavcodec/nvenc.h index 3602f16e83..b42b930920 100644 --- a/libavcodec/nvenc.h +++ b/libavcodec/nvenc.h @@ -56,7 +56,6 @@ typedef struct NVENCFrame { NV_ENC_OUTPUT_PTR out; NV_ENC_BUFFER_FORMAT format; - int locked; } NVENCFrame; typedef CUresult(CUDAAPI *PCUINIT)(unsigned int Flags); @@ -145,7 +144,7 @@ typedef struct NVENCContext { int nb_surfaces; NVENCFrame *frames; AVFifoBuffer *timestamps; - AVFifoBuffer *pending, *ready; + AVFifoBuffer *pending, *ready, *unused_surface_queue; struct { CUdeviceptr ptr; |