[FFmpeg-devel] [PATCH v6] avcodec/nvenc: write out user data unregistered SEI
Brad Hards
bradh at frogmouth.net
Tue May 25 14:19:15 EEST 2021
On Tuesday, 25 May 2021 9:03:51 PM AEST Timo Rothenpieler wrote:
> On 25/05/2021 12:11, Brad Hards wrote:
> > Signed-off-by: Brad Hards <bradh at frogmouth.net>
> > ---
> >
> > libavcodec/nvenc.c | 73 +++++++++++++++++++++++++++++++++++++---------
> > libavcodec/nvenc.h | 2 ++
> > 2 files changed, 62 insertions(+), 13 deletions(-)
> >
> > diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c
> > index 0dcd93a99c..9c2664a99e 100644
> > --- a/libavcodec/nvenc.c
> > +++ b/libavcodec/nvenc.c
> > @@ -1610,6 +1610,8 @@ av_cold int ff_nvenc_encode_close(AVCodecContext
> > *avctx)>
> > av_frame_free(&ctx->frame);
> >
> > + av_freep(&ctx->sei_data);
> > +
> >
> > if (ctx->nvencoder) {
> >
> > p_nvenc->nvEncDestroyEncoder(ctx->nvencoder);
> >
> > @@ -2170,9 +2172,9 @@ static int nvenc_send_frame(AVCodecContext *avctx,
> > const AVFrame *frame)>
> > NVENCSTATUS nv_status;
> > NvencSurface *tmp_out_surf, *in_surf;
> > int res, res2;
> >
> > - NV_ENC_SEI_PAYLOAD sei_data[8];
> >
> > int sei_count = 0;
> > int i;
> >
> > + int total_unregistered_sei = 0;
> >
> > NvencContext *ctx = avctx->priv_data;
> > NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs;
> >
> > @@ -2185,6 +2187,8 @@ static int nvenc_send_frame(AVCodecContext *avctx,
> > const AVFrame *frame)>
> > return AVERROR(EINVAL);
> >
> > if (frame && frame->buf[0]) {
> >
> > + void *a53_data = NULL;
> > + void *tc_data = NULL;
> >
> > in_surf = get_free_frame(ctx);
> > if (!in_surf)
> >
> > return AVERROR(EAGAIN);
> >
> > @@ -2230,7 +2234,6 @@ static int nvenc_send_frame(AVCodecContext *avctx,
> > const AVFrame *frame)>
> > pic_params.inputTimeStamp = frame->pts;
> >
> > if (ctx->a53_cc && av_frame_get_side_data(frame,
> > AV_FRAME_DATA_A53_CC)) {
> >
> > - void *a53_data = NULL;
> >
> > size_t a53_size = 0;
> >
> > if (ff_alloc_a53_sei(frame, 0, (void**)&a53_data, &a53_size)
> > < 0) {
> >
> > @@ -2238,15 +2241,23 @@ static int nvenc_send_frame(AVCodecContext *avctx,
> > const AVFrame *frame)>
> > }
> >
> > if (a53_data) {
> >
> > - sei_data[sei_count].payloadSize = (uint32_t)a53_size;
> > - sei_data[sei_count].payloadType = 4;
> > - sei_data[sei_count].payload = (uint8_t*)a53_data;
> > - sei_count ++;
> > + void *tmp = av_fast_realloc(ctx->sei_data,
> > + &(ctx->sei_data_size),
>
> The braces are unneccesary and I think against style guidelines as well.
Removed in v7
> > + sizeof(NV_ENC_SEI_PAYLOAD));
>
> I'd just pull the sei_count++ in there, and then use the same style
> fast_realloc in every block.
> As in: ++sei_count * sizeof(NV_ENC_SEI_PAYLOAD)
It doesn't work in the final block, but incorporated for a53 and s12m in v7
> > + if (!tmp) {
> > + av_free(a53_data);
> > + return AVERROR(ENOMEM);
> > + } else {
> > + ctx->sei_data = tmp;
> > + ctx->sei_data[sei_count].payloadSize =
> > (uint32_t)a53_size; +
> > ctx->sei_data[sei_count].payloadType = 4;
> > + ctx->sei_data[sei_count].payload =
> > (uint8_t*)a53_data;
> > + sei_count ++;
> > + }
> >
> > }
> >
> > }
> >
> > if (ctx->s12m_tc && av_frame_get_side_data(frame,
> > AV_FRAME_DATA_S12M_TIMECODE)) {>
> > - void *tc_data = NULL;
> >
> > size_t tc_size = 0;
> >
> > if (ff_alloc_timecode_sei(frame, avctx->framerate, 0,
> > (void**)&tc_data, &tc_size) < 0) {>
> > @@ -2254,14 +2265,50 @@ static int nvenc_send_frame(AVCodecContext *avctx,
> > const AVFrame *frame)>
> > }
> >
> > if (tc_data) {
> >
> > - sei_data[sei_count].payloadSize = (uint32_t)tc_size;
> > - sei_data[sei_count].payloadType = SEI_TYPE_TIME_CODE;
> > - sei_data[sei_count].payload = (uint8_t*)tc_data;
> > - sei_count ++;
> > + void *tmp = av_fast_realloc(ctx->sei_data,
> > + &(ctx->sei_data_size),
> > + (sei_count + 1) *
> > sizeof(NV_ENC_SEI_PAYLOAD));
> This seems to be indented one space too deep.
Removed in v7
> > + if (!tmp) {
> > + av_free(a53_data);
> > + av_free(tc_data);
> > + return AVERROR(ENOMEM);
> > + } else {
> > + ctx->sei_data = tmp;
> > + ctx->sei_data[sei_count].payloadSize =
> > (uint32_t)tc_size; +
> > ctx->sei_data[sei_count].payloadType = SEI_TYPE_TIME_CODE; +
> > ctx->sei_data[sei_count].payload = (uint8_t*)tc_data; +
> > sei_count ++;
> > + }
> > + }
> > + }
> > +
> > + for (int j = 0; j < frame->nb_side_data; j++)
> > + if (frame->side_data[j]->type ==
> > AV_FRAME_DATA_SEI_UNREGISTERED) +
> > total_unregistered_sei++;
> > + if (total_unregistered_sei > 0) {
> > + void *tmp = av_fast_realloc(ctx->sei_data,
> > + &(ctx->sei_data_size),
> > + (sei_count +
> > total_unregistered_sei) * sizeof(NV_ENC_SEI_PAYLOAD)); + if
> > (!tmp) {
> > + av_free(a53_data);
> > + av_free(tc_data);
> > + return AVERROR(ENOMEM);
> > + } else {
> > + ctx->sei_data = tmp;
> > + for (int j = 0; j < frame->nb_side_data; j++) {
> > + AVFrameSideData *side_data = frame->side_data[j];
> > + if (side_data->type ==
> > AV_FRAME_DATA_SEI_UNREGISTERED) { +
> > ctx->sei_data[sei_count].payloadSize = side_data->size; +
> > ctx->sei_data[sei_count].payloadType =
> > SEI_TYPE_USER_DATA_UNREGISTERED; +
> > ctx->sei_data[sei_count].payload = av_memdup(side_data->data,
> > side_data->size); + if
> > (ctx->sei_data[sei_count].payload)
> > + sei_count ++;
> > + }
> > + }
> >
> > }
> >
> > }
> >
> > - nvenc_codec_specific_pic_params(avctx, &pic_params, sei_data,
> > sei_count); + nvenc_codec_specific_pic_params(avctx, &pic_params,
> > ctx->sei_data, sei_count);>
> > } else {
> >
> > pic_params.encodePicFlags = NV_ENC_PIC_FLAG_EOS;
> >
> > }
> >
> > @@ -2273,7 +2320,7 @@ static int nvenc_send_frame(AVCodecContext *avctx,
> > const AVFrame *frame)>
> > nv_status = p_nvenc->nvEncEncodePicture(ctx->nvencoder,
> > &pic_params);
> >
> > for ( i = 0; i < sei_count; i++)
> >
> > - av_freep(&sei_data[i].payload);
> > + av_freep(&(ctx->sei_data[i].payload));
>
> I'm not 100% sure about these braces, but I think they're unneccesary as
> well.
Removed in v7
> > res = nvenc_pop_context(avctx);
> > if (res < 0)
> >
> > diff --git a/libavcodec/nvenc.h b/libavcodec/nvenc.h
> > index 314c270e74..d28f02b54f 100644
> > --- a/libavcodec/nvenc.h
> > +++ b/libavcodec/nvenc.h
> > @@ -165,6 +165,8 @@ typedef struct NvencContext
> >
> > AVFifoBuffer *output_surface_queue;
> > AVFifoBuffer *output_surface_ready_queue;
> > AVFifoBuffer *timestamp_list;
> >
> > + NV_ENC_SEI_PAYLOAD *sei_data;
> > + int sei_data_size;
> >
> > struct {
> >
> > void *ptr;
>
> Looks good otherwise, I will give it a test soon.
Thanks.
Brad
More information about the ffmpeg-devel
mailing list