|
|
|
@ -962,6 +962,10 @@ static av_cold int nvenc_recalc_surfaces(AVCodecContext *avctx) |
|
|
|
|
ctx->nb_surfaces = FFMAX(1, FFMIN(MAX_REGISTERED_FRAMES, ctx->nb_surfaces)); |
|
|
|
|
ctx->async_depth = FFMIN(ctx->async_depth, ctx->nb_surfaces - 1); |
|
|
|
|
|
|
|
|
|
// Output in the worst case will only start when the surface buffer is completely full.
|
|
|
|
|
// Hence we need to keep at least the max amount of surfaces plus the max reorder delay around.
|
|
|
|
|
ctx->frame_data_array_nb = ctx->nb_surfaces + ctx->encode_config.frameIntervalP - 1; |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -1750,6 +1754,10 @@ static av_cold int nvenc_setup_surfaces(AVCodecContext *avctx) |
|
|
|
|
if (!ctx->surfaces) |
|
|
|
|
return AVERROR(ENOMEM); |
|
|
|
|
|
|
|
|
|
ctx->frame_data_array = av_calloc(ctx->frame_data_array_nb, sizeof(*ctx->frame_data_array)); |
|
|
|
|
if (!ctx->frame_data_array) |
|
|
|
|
return AVERROR(ENOMEM); |
|
|
|
|
|
|
|
|
|
ctx->timestamp_list = av_fifo_alloc2(ctx->nb_surfaces, sizeof(int64_t), 0); |
|
|
|
|
if (!ctx->timestamp_list) |
|
|
|
|
return AVERROR(ENOMEM); |
|
|
|
@ -1840,6 +1848,12 @@ av_cold int ff_nvenc_encode_close(AVCodecContext *avctx) |
|
|
|
|
av_fifo_freep2(&ctx->output_surface_queue); |
|
|
|
|
av_fifo_freep2(&ctx->unused_surface_queue); |
|
|
|
|
|
|
|
|
|
if (ctx->frame_data_array) { |
|
|
|
|
for (i = 0; i < ctx->nb_surfaces; i++) |
|
|
|
|
av_buffer_unref(&ctx->frame_data_array[i].frame_opaque_ref); |
|
|
|
|
av_freep(&ctx->frame_data_array); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (ctx->surfaces && (avctx->pix_fmt == AV_PIX_FMT_CUDA || avctx->pix_fmt == AV_PIX_FMT_D3D11)) { |
|
|
|
|
for (i = 0; i < ctx->nb_registered_frames; i++) { |
|
|
|
|
if (ctx->registered_frames[i].mapped) |
|
|
|
@ -2211,6 +2225,65 @@ static int nvenc_set_timestamp(AVCodecContext *avctx, |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int nvenc_store_frame_data(AVCodecContext *avctx, NV_ENC_PIC_PARAMS *pic_params, const AVFrame *frame) |
|
|
|
|
{ |
|
|
|
|
NvencContext *ctx = avctx->priv_data; |
|
|
|
|
int res = 0; |
|
|
|
|
|
|
|
|
|
int idx = ctx->frame_data_array_pos; |
|
|
|
|
NvencFrameData *frame_data = &ctx->frame_data_array[idx]; |
|
|
|
|
|
|
|
|
|
// in case the encoder got reconfigured, there might be leftovers
|
|
|
|
|
av_buffer_unref(&frame_data->frame_opaque_ref); |
|
|
|
|
|
|
|
|
|
if (frame && frame->opaque_ref && avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) { |
|
|
|
|
frame_data->frame_opaque_ref = av_buffer_ref(frame->opaque_ref); |
|
|
|
|
if (!frame_data->frame_opaque_ref) |
|
|
|
|
return AVERROR(ENOMEM); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
frame_data->duration = frame->duration; |
|
|
|
|
frame_data->frame_opaque = frame->opaque; |
|
|
|
|
|
|
|
|
|
#if FF_API_REORDERED_OPAQUE |
|
|
|
|
FF_DISABLE_DEPRECATION_WARNINGS |
|
|
|
|
frame_data->reordered_opaque = frame->reordered_opaque; |
|
|
|
|
FF_ENABLE_DEPRECATION_WARNINGS |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
ctx->frame_data_array_pos = (ctx->frame_data_array_pos + 1) % ctx->frame_data_array_nb; |
|
|
|
|
pic_params->inputDuration = idx; |
|
|
|
|
|
|
|
|
|
return res; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int nvenc_retrieve_frame_data(AVCodecContext *avctx, NV_ENC_LOCK_BITSTREAM *lock_params, AVPacket *pkt) |
|
|
|
|
{ |
|
|
|
|
NvencContext *ctx = avctx->priv_data; |
|
|
|
|
int res = 0; |
|
|
|
|
|
|
|
|
|
int idx = lock_params->outputDuration; |
|
|
|
|
NvencFrameData *frame_data = &ctx->frame_data_array[idx]; |
|
|
|
|
|
|
|
|
|
pkt->duration = frame_data->duration; |
|
|
|
|
|
|
|
|
|
#if FF_API_REORDERED_OPAQUE |
|
|
|
|
FF_DISABLE_DEPRECATION_WARNINGS |
|
|
|
|
avctx->reordered_opaque = frame_data->reordered_opaque; |
|
|
|
|
FF_ENABLE_DEPRECATION_WARNINGS |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) { |
|
|
|
|
pkt->opaque = frame_data->frame_opaque; |
|
|
|
|
pkt->opaque_ref = frame_data->frame_opaque_ref; |
|
|
|
|
frame_data->frame_opaque_ref = NULL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
av_buffer_unref(&frame_data->frame_opaque_ref); |
|
|
|
|
|
|
|
|
|
return res; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int process_output_surface(AVCodecContext *avctx, AVPacket *pkt, NvencSurface *tmpoutsurf) |
|
|
|
|
{ |
|
|
|
|
NvencContext *ctx = avctx->priv_data; |
|
|
|
@ -2297,6 +2370,10 @@ static int process_output_surface(AVCodecContext *avctx, AVPacket *pkt, NvencSur |
|
|
|
|
if (res < 0) |
|
|
|
|
goto error2; |
|
|
|
|
|
|
|
|
|
res = nvenc_retrieve_frame_data(avctx, &lock_params, pkt); |
|
|
|
|
if (res < 0) |
|
|
|
|
goto error2; |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
|
|
error: |
|
|
|
@ -2592,6 +2669,10 @@ static int nvenc_send_frame(AVCodecContext *avctx, const AVFrame *frame) |
|
|
|
|
sei_count = res; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
res = nvenc_store_frame_data(avctx, &pic_params, frame); |
|
|
|
|
if (res < 0) |
|
|
|
|
return res; |
|
|
|
|
|
|
|
|
|
nvenc_codec_specific_pic_params(avctx, &pic_params, ctx->sei_data, sei_count); |
|
|
|
|
} else { |
|
|
|
|
pic_params.encodePicFlags = NV_ENC_PIC_FLAG_EOS; |
|
|
|
|