mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-04-14 00:58:38 +02:00
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).
This commit is contained in:
parent
bb65eb6299
commit
2e8d88ad52
@ -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)
|
|||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
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, ¶ms, pkt);
|
ret = nvenc_set_timestamp(avctx, ¶ms, pkt);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
|
@ -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 {
|
|||||||
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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user