[FFmpeg-devel] [PATCH v7] avcodec/nvenc: write out user data unregistered SEI

Brad Hards bradh at frogmouth.net
Tue Jun 1 12:51:27 EEST 2021


On Tuesday, 25 May 2021 9:16:35 PM AEST Brad Hards wrote:
> Signed-off-by: Brad Hards <bradh at frogmouth.net>
> ---
>  libavcodec/nvenc.c | 71 +++++++++++++++++++++++++++++++++++++---------
>  libavcodec/nvenc.h |  2 ++
>  2 files changed, 60 insertions(+), 13 deletions(-)
> 
> diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c
> index 0dcd93a99c..8ca5cab4c8 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,22 @@ 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,
> +                                            ++sei_count *
> sizeof(NV_ENC_SEI_PAYLOAD)); +                if (!tmp) {
> +                    av_free(a53_data);
> +                    return AVERROR(ENOMEM);
> +                } else {
> +                    ctx->sei_data = tmp;
> +                    ctx->sei_data[sei_count-1].payloadSize =
> (uint32_t)a53_size; +                   
> ctx->sei_data[sei_count-1].payloadType = 4;
> +                    ctx->sei_data[sei_count-1].payload =
> (uint8_t*)a53_data; +                }
>              }
>          }
> 
>          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 +2264,49 @@ 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 *
> sizeof(NV_ENC_SEI_PAYLOAD)); +                if (!tmp) {
> +                    av_free(a53_data);
> +                    av_free(tc_data);
> +                    return AVERROR(ENOMEM);
> +                } else {
> +                    ctx->sei_data = tmp;
> +                    ctx->sei_data[sei_count-1].payloadSize =
> (uint32_t)tc_size; +                   
> ctx->sei_data[sei_count-1].payloadType = SEI_TYPE_TIME_CODE; +             
>       ctx->sei_data[sei_count-1].payload = (uint8_t*)tc_data; +            
>    }
> +            }
> +        }
> +
> +        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 +2318,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);
> 
>      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;
Anything more on this version?

Brad





More information about the ffmpeg-devel mailing list