Commit 2e8d88ad authored by Ben Chang's avatar Ben Chang Committed by Luca Barbato

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).
parent bb65eb62
...@@ -986,6 +986,7 @@ static int nvenc_alloc_surface(AVCodecContext *avctx, int idx) ...@@ -986,6 +986,7 @@ static int nvenc_alloc_surface(AVCodecContext *avctx, int idx)
{ {
NVENCContext *ctx = avctx->priv_data; NVENCContext *ctx = avctx->priv_data;
NV_ENCODE_API_FUNCTION_LIST *nv = &ctx->nvel.nvenc_funcs; NV_ENCODE_API_FUNCTION_LIST *nv = &ctx->nvel.nvenc_funcs;
NVENCFrame *tmp_surface = &ctx->frames[idx];
int ret; int ret;
NV_ENC_CREATE_BITSTREAM_BUFFER out_buffer = { 0 }; NV_ENC_CREATE_BITSTREAM_BUFFER out_buffer = { 0 };
...@@ -1046,6 +1047,8 @@ static int nvenc_alloc_surface(AVCodecContext *avctx, int idx) ...@@ -1046,6 +1047,8 @@ static int nvenc_alloc_surface(AVCodecContext *avctx, int idx)
ctx->frames[idx].out = out_buffer.bitstreamBuffer; ctx->frames[idx].out = out_buffer.bitstreamBuffer;
av_fifo_generic_write(ctx->unused_surface_queue, &tmp_surface, sizeof(tmp_surface), NULL);
return 0; return 0;
} }
...@@ -1066,6 +1069,9 @@ static int nvenc_setup_surfaces(AVCodecContext *avctx) ...@@ -1066,6 +1069,9 @@ static int nvenc_setup_surfaces(AVCodecContext *avctx)
ctx->timestamps = av_fifo_alloc(ctx->nb_surfaces * sizeof(int64_t)); ctx->timestamps = av_fifo_alloc(ctx->nb_surfaces * sizeof(int64_t));
if (!ctx->timestamps) if (!ctx->timestamps)
return AVERROR(ENOMEM); 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)); ctx->pending = av_fifo_alloc(ctx->nb_surfaces * sizeof(*ctx->frames));
if (!ctx->pending) if (!ctx->pending)
return AVERROR(ENOMEM); return AVERROR(ENOMEM);
...@@ -1123,6 +1129,7 @@ av_cold int ff_nvenc_encode_close(AVCodecContext *avctx) ...@@ -1123,6 +1129,7 @@ av_cold int ff_nvenc_encode_close(AVCodecContext *avctx)
av_fifo_free(ctx->timestamps); av_fifo_free(ctx->timestamps);
av_fifo_free(ctx->pending); av_fifo_free(ctx->pending);
av_fifo_free(ctx->ready); av_fifo_free(ctx->ready);
av_fifo_free(ctx->unused_surface_queue);
if (ctx->frames) { if (ctx->frames) {
for (i = 0; i < ctx->nb_surfaces; ++i) { for (i = 0; i < ctx->nb_surfaces; ++i) {
...@@ -1201,16 +1208,14 @@ av_cold int ff_nvenc_encode_init(AVCodecContext *avctx) ...@@ -1201,16 +1208,14 @@ av_cold int ff_nvenc_encode_init(AVCodecContext *avctx)
static NVENCFrame *get_free_frame(NVENCContext *ctx) static NVENCFrame *get_free_frame(NVENCContext *ctx)
{ {
int i; NVENCFrame *tmp_surf;
for (i = 0; i < ctx->nb_surfaces; i++) { if (!(av_fifo_size(ctx->unused_surface_queue) > 0))
if (!ctx->frames[i].locked) { // queue empty
ctx->frames[i].locked = 1; return NULL;
return &ctx->frames[i];
}
}
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) 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) ...@@ -1510,7 +1515,7 @@ static int nvenc_get_output(AVCodecContext *avctx, AVPacket *pkt)
frame->in = NULL; frame->in = NULL;
} }
frame->locked = 0; av_fifo_generic_write(ctx->unused_surface_queue, &frame, sizeof(frame), NULL);
ret = nvenc_set_timestamp(avctx, &params, pkt); ret = nvenc_set_timestamp(avctx, &params, pkt);
if (ret < 0) if (ret < 0)
......
...@@ -56,7 +56,6 @@ typedef struct NVENCFrame { ...@@ -56,7 +56,6 @@ typedef struct NVENCFrame {
NV_ENC_OUTPUT_PTR out; NV_ENC_OUTPUT_PTR out;
NV_ENC_BUFFER_FORMAT format; NV_ENC_BUFFER_FORMAT format;
int locked;
} NVENCFrame; } NVENCFrame;
typedef CUresult(CUDAAPI *PCUINIT)(unsigned int Flags); typedef CUresult(CUDAAPI *PCUINIT)(unsigned int Flags);
...@@ -145,7 +144,7 @@ typedef struct NVENCContext { ...@@ -145,7 +144,7 @@ typedef struct NVENCContext {
int nb_surfaces; int nb_surfaces;
NVENCFrame *frames; NVENCFrame *frames;
AVFifoBuffer *timestamps; AVFifoBuffer *timestamps;
AVFifoBuffer *pending, *ready; AVFifoBuffer *pending, *ready, *unused_surface_queue;
struct { struct {
CUdeviceptr ptr; CUdeviceptr ptr;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment