On Saturday, May 25, 2019, James Almer <jamr...@gmail.com> wrote: > On 5/22/2019 3:59 AM, lance.lmw...@gmail.com wrote: > > From: Limin Wang <lance.lmw...@gmail.com> > > > > The testing command for the HDR10 output with nvenc: > > $ ./ffmpeg_g -y -i 4K.mp4 -c:v hevc_nvenc -g 7 -color_primaries bt2020 > -colorspace bt2020_ncl -color_trc smpte2084 -sei hdr10 \ > > -master_display "G(13250,34500)B(7500,3000)R( > 34000,16000)WP(15635,16450)L(10000000,50)" -max_cll "0, 0" test.ts > > > > Please notice it is preferable to use the frame sei side data than > master_display and max_cll paramters config > > --- > > libavcodec/nvenc.c | 129 ++++++++++++++++++++++++++++++++++++++++ > > libavcodec/nvenc.h | 18 ++++++ > > libavcodec/nvenc_hevc.c | 11 ++++ > > 3 files changed, 158 insertions(+) > > > > diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c > > index 75dda6d689..3fd0eca4a5 100644 > > --- a/libavcodec/nvenc.c > > +++ b/libavcodec/nvenc.c > > @@ -22,6 +22,9 @@ > > #include "config.h" > > > > #include "nvenc.h" > > +#include "cbs_h265.h" > > This doesn't seem right. The encoder isn't using this framework at all. > > You're apparently including this only to get the > H265RawSEIMasteringDisplayColourVolume and > H265RawSEIContentLightLevelInfo structs, which you don't really need to > fill sei_data[i].payload > > OK, I'll remove the dependent for the two structure and update the patch.
> > +#include "hevc_sei.h" > > +#include "put_bits.h" > > > > #include "libavutil/hwcontext_cuda.h" > > #include "libavutil/hwcontext.h" > > @@ -30,6 +33,7 @@ > > #include "libavutil/avassert.h" > > #include "libavutil/mem.h" > > #include "libavutil/pixdesc.h" > > +#include "libavutil/mastering_display_metadata.h" > > #include "internal.h" > > > > #define CHECK_CU(x) FF_CUDA_CHECK_DL(avctx, dl_fn->cuda_dl, x) > > @@ -1491,6 +1495,46 @@ av_cold int ff_nvenc_encode_init(AVCodecContext > *avctx) > > ctx->data_pix_fmt = avctx->pix_fmt; > > } > > > > + ctx->display_primaries_x[0] = 13250; > > + ctx->display_primaries_y[0] = 34500; > > + ctx->display_primaries_x[1] = 7500; > > + ctx->display_primaries_y[1] = 3000; > > + ctx->display_primaries_x[2] = 34000; > > + ctx->display_primaries_y[2] = 16000; > > + ctx->white_point_x = 15635; > > + ctx->white_point_y = 16450; > > + ctx->max_display_mastering_luminance = 10000000; > > + ctx->min_display_mastering_luminance = 500; > > + ctx->max_content_light_level = 0; > > + ctx->max_pic_average_light_level = 0; > > + if (ctx->master_display) { > > + ret = sscanf(ctx->master_display, "G(%hu,%hu)B(%hu,%hu)R(%hu,% > hu)WP(%hu,%hu)L(%u,%u)", > > + &ctx->display_primaries_x[0], > &ctx->display_primaries_y[0], > > + &ctx->display_primaries_x[1], > &ctx->display_primaries_y[1], > > + &ctx->display_primaries_x[2], > &ctx->display_primaries_y[2], > > + &ctx->white_point_x, &ctx->white_point_y, > > + &ctx->max_display_mastering_luminance, > &ctx->min_display_mastering_luminance); > > + if (ret != 10) { > > + ret = sscanf(ctx->master_display, > "G[%hu,%hu]B[%hu,%hu]R[%hu,%hu]WP[%hu,%hu]L[%u,%u]", > > + &ctx->display_primaries_x[0], > &ctx->display_primaries_y[0], > > + &ctx->display_primaries_x[1], > &ctx->display_primaries_y[1], > > + &ctx->display_primaries_x[2], > &ctx->display_primaries_y[2], > > + &ctx->white_point_x, &ctx->white_point_y, > > + &ctx->max_display_mastering_luminance, > &ctx->min_display_mastering_luminance); > > + } > > + > > + if (ret != 10) { > > + av_log(avctx, AV_LOG_INFO, "Failed to parse master > display(%s)\n", ctx->master_display); > > + } > > + } > > + > > + if (ctx->max_cll) { > > + ret = sscanf(ctx->max_cll, "%hu,%hu", > &ctx->max_content_light_level, &ctx->max_pic_average_light_level); > > + if (ret != 2) { > > + av_log(avctx, AV_LOG_INFO, "Failed to parse max cll(%s)\n", > ctx->max_cll); > > + } > > + } > > + > > if ((ret = nvenc_load_libraries(avctx)) < 0) > > return ret; > > > > @@ -2110,6 +2154,91 @@ int ff_nvenc_send_frame(AVCodecContext *avctx, > const AVFrame *frame) > > } > > } > > > > + if (ctx->sei & SEI_MASTERING_DISPLAY) { > > + AVFrameSideData *sd = av_frame_get_side_data(frame, > AV_FRAME_DATA_MASTERING_DISPLAY_METADATA); > > + H265RawSEIMasteringDisplayColourVolume smd; > > + > > + if (sd) { > > + AVMasteringDisplayMetadata *mdm = > (AVMasteringDisplayMetadata *)sd->data; > > + // HEVC uses a g,b,r ordering, which we convert from a > more natural r,g,b > > + const int mapping[3] = {2, 0, 1}; > > + const int chroma_den = 50000; > > + const int luma_den = 10000; > > + > > + if (mdm->has_primaries && mdm->has_luminance) { > > + > > + for (i = 0; i < 3; i++) { > > + const int j = mapping[i]; > > + smd.display_primaries_x[i] = chroma_den * > av_q2d(mdm->display_primaries[j][0]); > > + smd.display_primaries_y[i] = chroma_den * > av_q2d( mdm->display_primaries[j][1]); > > + } > > + > > + smd.white_point_x = chroma_den * > av_q2d(mdm->white_point[0]); > > + smd.white_point_y = chroma_den * > av_q2d(mdm->white_point[1]); > > + smd.max_display_mastering_luminance = luma_den * > av_q2d(mdm->max_luminance); > > + smd.min_display_mastering_luminance = luma_den * > av_q2d(mdm->min_luminance); > > + } > > + } else { > > + for (i = 0; i < 3; i++) { > > + smd.display_primaries_x[i] = > ctx->display_primaries_x[i]; > > + smd.display_primaries_y[i] = > ctx->display_primaries_y[i]; > > + } > > + smd.white_point_x = ctx->white_point_x; > > + smd.white_point_y = ctx->white_point_y; > > + smd.max_display_mastering_luminance = > ctx->max_display_mastering_luminance; > > + smd.min_display_mastering_luminance = > ctx->min_display_mastering_luminance; > > + } > > + > > + sei_data[sei_count].payloadSize = sizeof( > H265RawSEIMasteringDisplayColourVolume); > > + sei_data[sei_count].payloadType = HEVC_SEI_TYPE_MASTERING_ > DISPLAY_INFO; > > + sei_data[sei_count].payload = > av_mallocz(sei_data[sei_count].payloadSize); > > + if (sei_data[sei_count].payload) { > > + PutBitContext pb; > > + > > + init_put_bits(&pb, sei_data[sei_count].payload, > sei_data[sei_count].payloadSize); > > + for (i = 0; i < 3; i++) { > > + put_bits(&pb, 16, smd.display_primaries_x[i]); > > + put_bits(&pb, 16, smd.display_primaries_y[i]); > > + } > > + put_bits(&pb, 16, smd.white_point_x); > > + put_bits(&pb, 16, smd.white_point_y); > > + put_bits(&pb, 32, smd.max_display_mastering_luminance); > > + put_bits(&pb, 32, smd.min_display_mastering_luminance); > > + flush_put_bits(&pb); > > + > > + sei_count ++; > > + } > > + } > > + > > + if (ctx->sei & SEI_CONTENT_LIGHT_LEVEL) { > > + AVFrameSideData *sd = av_frame_get_side_data(frame, > AV_FRAME_DATA_CONTENT_LIGHT_LEVEL); > > + H265RawSEIContentLightLevelInfo clli; > > + > > + if (sd) { > > + AVContentLightMetadata *clm = (AVContentLightMetadata > *)sd->data; > > + > > + clli.max_content_light_level = FFMIN(clm->MaxCLL, > 65535); > > + clli.max_pic_average_light_level = FFMIN(clm->MaxFALL, > 65535); > > + } else { > > + clli.max_content_light_level = > ctx->max_content_light_level; > > + clli.max_pic_average_light_level = > ctx->max_pic_average_light_level; > > + } > > + > > + sei_data[sei_count].payloadSize = sizeof( > H265RawSEIContentLightLevelInfo); > > + sei_data[sei_count].payloadType = > HEVC_SEI_TYPE_CONTENT_LIGHT_LEVEL_INFO; > > + sei_data[sei_count].payload = > av_mallocz(sei_data[sei_count].payloadSize); > > + if (sei_data[sei_count].payload) { > > + PutBitContext pb; > > + > > + init_put_bits(&pb, sei_data[sei_count].payload, > sei_data[sei_count].payloadSize); > > + put_bits(&pb, 16, clli.max_content_light_level); > > + put_bits(&pb, 16, clli.max_pic_average_light_level); > > + flush_put_bits(&pb); > > + > > + sei_count ++; > > + } > > + } > > + > > nvenc_codec_specific_pic_params(avctx, &pic_params, sei_data, > sei_count); > > } else { > > pic_params.encodePicFlags = NV_ENC_PIC_FLAG_EOS; > > diff --git a/libavcodec/nvenc.h b/libavcodec/nvenc.h > > index ddd6168409..583c48d090 100644 > > --- a/libavcodec/nvenc.h > > +++ b/libavcodec/nvenc.h > > @@ -54,6 +54,11 @@ typedef void ID3D11Device; > > #define NVENC_HAVE_HEVC_BFRAME_REF_MODE > > #endif > > > > +enum { > > + SEI_MASTERING_DISPLAY = 0x08, > > + SEI_CONTENT_LIGHT_LEVEL = 0x10, > > +}; > > + > > typedef struct NvencSurface > > { > > NV_ENC_INPUT_PTR input_surface; > > @@ -192,6 +197,19 @@ typedef struct NvencContext > > int coder; > > int b_ref_mode; > > int a53_cc; > > + uint64_t sei; > > + > > + char *master_display; > > + char *max_cll; > > + uint16_t display_primaries_x[3]; > > + uint16_t display_primaries_y[3]; > > + uint16_t white_point_x; > > + uint16_t white_point_y; > > + uint32_t max_display_mastering_luminance; > > + uint32_t min_display_mastering_luminance; > > + > > + uint16_t max_content_light_level; > > + uint16_t max_pic_average_light_level; > > } NvencContext; > > > > int ff_nvenc_encode_init(AVCodecContext *avctx); > > diff --git a/libavcodec/nvenc_hevc.c b/libavcodec/nvenc_hevc.c > > index d567d960ba..74ebd03d8e 100644 > > --- a/libavcodec/nvenc_hevc.c > > +++ b/libavcodec/nvenc_hevc.c > > @@ -127,6 +127,17 @@ static const AVOption options[] = { > > { "each", "", 0, > AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, VE, "b_ref_mode" }, > > { "middle", "", 0, > AV_OPT_TYPE_CONST, { .i64 = 2 }, 0, 0, VE, "b_ref_mode" }, > > #endif > > + { "sei", "Set SEI to include", > > + > OFFSET(sei), AV_OPT_TYPE_FLAGS, > > + { .i64 = > SEI_MASTERING_DISPLAY | SEI_CONTENT_LIGHT_LEVEL }, > > + 0, INT_MAX, > VE, "sei" }, > > + { "hdr10","Include HDR metadata for mastering display colour volume > and content light level information", > > + 0, > AV_OPT_TYPE_CONST, { .i64 = SEI_MASTERING_DISPLAY | > SEI_CONTENT_LIGHT_LEVEL }, > > + 0, 0, VE, > "sei" }, > > + { "master_display", "SMPTE ST 2086 master display color volume > info SEI (HDR), the string format is: \"G(x,y)B(x,y)R(x,y)WP(x,y)L( > max,min)\"", > > + > OFFSET(master_display), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, VE }, > > + { "max_cll", "content light level info, the string > format is: \"cll, fall\"", > > + > OFFSET(max_cll), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, VE }, > > { NULL } > > }; > > > > > > _______________________________________________ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > > To unsubscribe, visit link above, or email > ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe". _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".