From 6169bd0feaec518a6aacbb3497711052a707e3c2 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 23 Feb 2024 10:21:54 +0100 Subject: [PATCH] lavc/*dec: use side data preference for mastering display/content light metadata --- libavcodec/av1dec.c | 46 +++++++++++--------- libavcodec/h2645_sei.c | 97 +++++++++++++++++++++++------------------- libavcodec/libdav1d.c | 47 +++++++++++--------- libavcodec/pngdec.c | 54 +++++++++++++---------- libavcodec/qsvdec.c | 50 +++++++++++++--------- 5 files changed, 166 insertions(+), 128 deletions(-) diff --git a/libavcodec/av1dec.c b/libavcodec/av1dec.c index af80ee0b17..bbb5634773 100644 --- a/libavcodec/av1dec.c +++ b/libavcodec/av1dec.c @@ -999,31 +999,39 @@ static int export_metadata(AVCodecContext *avctx, AVFrame *frame) int ret = 0; if (s->mdcv) { - AVMasteringDisplayMetadata *mastering = av_mastering_display_metadata_create_side_data(frame); - if (!mastering) - return AVERROR(ENOMEM); + AVMasteringDisplayMetadata *mastering; - for (int i = 0; i < 3; i++) { - mastering->display_primaries[i][0] = av_make_q(s->mdcv->primary_chromaticity_x[i], 1 << 16); - mastering->display_primaries[i][1] = av_make_q(s->mdcv->primary_chromaticity_y[i], 1 << 16); + ret = ff_decode_mastering_display_new(avctx, frame, &mastering); + if (ret < 0) + return ret; + + if (mastering) { + for (int i = 0; i < 3; i++) { + mastering->display_primaries[i][0] = av_make_q(s->mdcv->primary_chromaticity_x[i], 1 << 16); + mastering->display_primaries[i][1] = av_make_q(s->mdcv->primary_chromaticity_y[i], 1 << 16); + } + mastering->white_point[0] = av_make_q(s->mdcv->white_point_chromaticity_x, 1 << 16); + mastering->white_point[1] = av_make_q(s->mdcv->white_point_chromaticity_y, 1 << 16); + + mastering->max_luminance = av_make_q(s->mdcv->luminance_max, 1 << 8); + mastering->min_luminance = av_make_q(s->mdcv->luminance_min, 1 << 14); + + mastering->has_primaries = 1; + mastering->has_luminance = 1; } - mastering->white_point[0] = av_make_q(s->mdcv->white_point_chromaticity_x, 1 << 16); - mastering->white_point[1] = av_make_q(s->mdcv->white_point_chromaticity_y, 1 << 16); - - mastering->max_luminance = av_make_q(s->mdcv->luminance_max, 1 << 8); - mastering->min_luminance = av_make_q(s->mdcv->luminance_min, 1 << 14); - - mastering->has_primaries = 1; - mastering->has_luminance = 1; } if (s->cll) { - AVContentLightMetadata *light = av_content_light_metadata_create_side_data(frame); - if (!light) - return AVERROR(ENOMEM); + AVContentLightMetadata *light; - light->MaxCLL = s->cll->max_cll; - light->MaxFALL = s->cll->max_fall; + ret = ff_decode_content_light_new(avctx, frame, &light); + if (ret < 0) + return ret; + + if (light) { + light->MaxCLL = s->cll->max_cll; + light->MaxFALL = s->cll->max_fall; + } } while (av_fifo_read(s->itut_t35_fifo, &itut_t35, 1) >= 0) { diff --git a/libavcodec/h2645_sei.c b/libavcodec/h2645_sei.c index cb6be0594b..e60606f43f 100644 --- a/libavcodec/h2645_sei.c +++ b/libavcodec/h2645_sei.c @@ -35,6 +35,7 @@ #include "atsc_a53.h" #include "avcodec.h" +#include "decode.h" #include "dynamic_hdr_vivid.h" #include "get_bits.h" #include "golomb.h" @@ -515,6 +516,7 @@ int ff_h2645_sei_to_frame(AVFrame *frame, H2645SEI *sei, int seed) { H2645SEIFramePacking *fp = &sei->frame_packing; + int ret; if (fp->present && is_frame_packing_type_valid(fp->arrangement_type, codec_id) && @@ -710,56 +712,63 @@ int ff_h2645_sei_to_frame(AVFrame *frame, H2645SEI *sei, const int chroma_den = 50000; const int luma_den = 10000; int i; - AVMasteringDisplayMetadata *metadata = - av_mastering_display_metadata_create_side_data(frame); - if (!metadata) - return AVERROR(ENOMEM); + AVMasteringDisplayMetadata *metadata; - for (i = 0; i < 3; i++) { - const int j = mapping[i]; - metadata->display_primaries[i][0].num = sei->mastering_display.display_primaries[j][0]; - metadata->display_primaries[i][0].den = chroma_den; - metadata->display_primaries[i][1].num = sei->mastering_display.display_primaries[j][1]; - metadata->display_primaries[i][1].den = chroma_den; + ret = ff_decode_mastering_display_new(avctx, frame, &metadata); + if (ret < 0) + return ret; + + if (metadata) { + for (i = 0; i < 3; i++) { + const int j = mapping[i]; + metadata->display_primaries[i][0].num = sei->mastering_display.display_primaries[j][0]; + metadata->display_primaries[i][0].den = chroma_den; + metadata->display_primaries[i][1].num = sei->mastering_display.display_primaries[j][1]; + metadata->display_primaries[i][1].den = chroma_den; + } + metadata->white_point[0].num = sei->mastering_display.white_point[0]; + metadata->white_point[0].den = chroma_den; + metadata->white_point[1].num = sei->mastering_display.white_point[1]; + metadata->white_point[1].den = chroma_den; + + metadata->max_luminance.num = sei->mastering_display.max_luminance; + metadata->max_luminance.den = luma_den; + metadata->min_luminance.num = sei->mastering_display.min_luminance; + metadata->min_luminance.den = luma_den; + metadata->has_luminance = 1; + metadata->has_primaries = 1; + + av_log(avctx, AV_LOG_DEBUG, "Mastering Display Metadata:\n"); + av_log(avctx, AV_LOG_DEBUG, + "r(%5.4f,%5.4f) g(%5.4f,%5.4f) b(%5.4f %5.4f) wp(%5.4f, %5.4f)\n", + av_q2d(metadata->display_primaries[0][0]), + av_q2d(metadata->display_primaries[0][1]), + av_q2d(metadata->display_primaries[1][0]), + av_q2d(metadata->display_primaries[1][1]), + av_q2d(metadata->display_primaries[2][0]), + av_q2d(metadata->display_primaries[2][1]), + av_q2d(metadata->white_point[0]), av_q2d(metadata->white_point[1])); + av_log(avctx, AV_LOG_DEBUG, + "min_luminance=%f, max_luminance=%f\n", + av_q2d(metadata->min_luminance), av_q2d(metadata->max_luminance)); } - metadata->white_point[0].num = sei->mastering_display.white_point[0]; - metadata->white_point[0].den = chroma_den; - metadata->white_point[1].num = sei->mastering_display.white_point[1]; - metadata->white_point[1].den = chroma_den; - - metadata->max_luminance.num = sei->mastering_display.max_luminance; - metadata->max_luminance.den = luma_den; - metadata->min_luminance.num = sei->mastering_display.min_luminance; - metadata->min_luminance.den = luma_den; - metadata->has_luminance = 1; - metadata->has_primaries = 1; - - av_log(avctx, AV_LOG_DEBUG, "Mastering Display Metadata:\n"); - av_log(avctx, AV_LOG_DEBUG, - "r(%5.4f,%5.4f) g(%5.4f,%5.4f) b(%5.4f %5.4f) wp(%5.4f, %5.4f)\n", - av_q2d(metadata->display_primaries[0][0]), - av_q2d(metadata->display_primaries[0][1]), - av_q2d(metadata->display_primaries[1][0]), - av_q2d(metadata->display_primaries[1][1]), - av_q2d(metadata->display_primaries[2][0]), - av_q2d(metadata->display_primaries[2][1]), - av_q2d(metadata->white_point[0]), av_q2d(metadata->white_point[1])); - av_log(avctx, AV_LOG_DEBUG, - "min_luminance=%f, max_luminance=%f\n", - av_q2d(metadata->min_luminance), av_q2d(metadata->max_luminance)); } if (sei->content_light.present) { - AVContentLightMetadata *metadata = - av_content_light_metadata_create_side_data(frame); - if (!metadata) - return AVERROR(ENOMEM); - metadata->MaxCLL = sei->content_light.max_content_light_level; - metadata->MaxFALL = sei->content_light.max_pic_average_light_level; + AVContentLightMetadata *metadata; - av_log(avctx, AV_LOG_DEBUG, "Content Light Level Metadata:\n"); - av_log(avctx, AV_LOG_DEBUG, "MaxCLL=%d, MaxFALL=%d\n", - metadata->MaxCLL, metadata->MaxFALL); + ret = ff_decode_content_light_new(avctx, frame, &metadata); + if (ret < 0) + return ret; + + if (metadata) { + metadata->MaxCLL = sei->content_light.max_content_light_level; + metadata->MaxFALL = sei->content_light.max_pic_average_light_level; + + av_log(avctx, AV_LOG_DEBUG, "Content Light Level Metadata:\n"); + av_log(avctx, AV_LOG_DEBUG, "MaxCLL=%d, MaxFALL=%d\n", + metadata->MaxCLL, metadata->MaxFALL); + } } return 0; diff --git a/libavcodec/libdav1d.c b/libavcodec/libdav1d.c index fdc87d396c..5c4c643696 100644 --- a/libavcodec/libdav1d.c +++ b/libavcodec/libdav1d.c @@ -487,33 +487,38 @@ static int libdav1d_receive_frame(AVCodecContext *c, AVFrame *frame) } if (p->mastering_display) { - AVMasteringDisplayMetadata *mastering = av_mastering_display_metadata_create_side_data(frame); - if (!mastering) { - res = AVERROR(ENOMEM); + AVMasteringDisplayMetadata *mastering; + + res = ff_decode_mastering_display_new(c, frame, &mastering); + if (res < 0) goto fail; + + if (mastering) { + for (int i = 0; i < 3; i++) { + mastering->display_primaries[i][0] = av_make_q(p->mastering_display->primaries[i][0], 1 << 16); + mastering->display_primaries[i][1] = av_make_q(p->mastering_display->primaries[i][1], 1 << 16); + } + mastering->white_point[0] = av_make_q(p->mastering_display->white_point[0], 1 << 16); + mastering->white_point[1] = av_make_q(p->mastering_display->white_point[1], 1 << 16); + + mastering->max_luminance = av_make_q(p->mastering_display->max_luminance, 1 << 8); + mastering->min_luminance = av_make_q(p->mastering_display->min_luminance, 1 << 14); + + mastering->has_primaries = 1; + mastering->has_luminance = 1; } - - for (int i = 0; i < 3; i++) { - mastering->display_primaries[i][0] = av_make_q(p->mastering_display->primaries[i][0], 1 << 16); - mastering->display_primaries[i][1] = av_make_q(p->mastering_display->primaries[i][1], 1 << 16); - } - mastering->white_point[0] = av_make_q(p->mastering_display->white_point[0], 1 << 16); - mastering->white_point[1] = av_make_q(p->mastering_display->white_point[1], 1 << 16); - - mastering->max_luminance = av_make_q(p->mastering_display->max_luminance, 1 << 8); - mastering->min_luminance = av_make_q(p->mastering_display->min_luminance, 1 << 14); - - mastering->has_primaries = 1; - mastering->has_luminance = 1; } if (p->content_light) { - AVContentLightMetadata *light = av_content_light_metadata_create_side_data(frame); - if (!light) { - res = AVERROR(ENOMEM); + AVContentLightMetadata *light; + + res = ff_decode_content_light_new(c, frame, &light); + if (res < 0) goto fail; + + if (light) { + light->MaxCLL = p->content_light->max_content_light_level; + light->MaxFALL = p->content_light->max_frame_average_light_level; } - light->MaxCLL = p->content_light->max_content_light_level; - light->MaxFALL = p->content_light->max_frame_average_light_level; } if (p->itut_t35) { #if FF_DAV1D_VERSION_AT_LEAST(6,9) diff --git a/libavcodec/pngdec.c b/libavcodec/pngdec.c index 8f409c74b8..de50e6a5b6 100644 --- a/libavcodec/pngdec.c +++ b/libavcodec/pngdec.c @@ -746,33 +746,41 @@ static int populate_avctx_color_fields(AVCodecContext *avctx, AVFrame *frame) avctx->bits_per_raw_sample = s->significant_bits; if (s->have_clli) { - AVContentLightMetadata *clli = - av_content_light_metadata_create_side_data(frame); - if (!clli) - return AVERROR(ENOMEM); - /* - * 0.0001 divisor value - * see: https://www.w3.org/TR/png-3/#cLLi-chunk - */ - clli->MaxCLL = s->clli_max / 10000; - clli->MaxFALL = s->clli_avg / 10000; + AVContentLightMetadata *clli; + + ret = ff_decode_content_light_new(avctx, frame, &clli); + if (ret < 0) + return ret; + + if (clli) { + /* + * 0.0001 divisor value + * see: https://www.w3.org/TR/png-3/#cLLi-chunk + */ + clli->MaxCLL = s->clli_max / 10000; + clli->MaxFALL = s->clli_avg / 10000; + } } if (s->have_mdvc) { - AVMasteringDisplayMetadata *mdvc = - av_mastering_display_metadata_create_side_data(frame); - if (!mdvc) - return AVERROR(ENOMEM); - mdvc->has_primaries = 1; - for (int i = 0; i < 3; i++) { - mdvc->display_primaries[i][0] = av_make_q(s->mdvc_primaries[i][0], 50000); - mdvc->display_primaries[i][1] = av_make_q(s->mdvc_primaries[i][1], 50000); + AVMasteringDisplayMetadata *mdvc; + + ret = ff_decode_mastering_display_new(avctx, frame, &mdvc); + if (ret < 0) + return ret; + + if (mdvc) { + mdvc->has_primaries = 1; + for (int i = 0; i < 3; i++) { + mdvc->display_primaries[i][0] = av_make_q(s->mdvc_primaries[i][0], 50000); + mdvc->display_primaries[i][1] = av_make_q(s->mdvc_primaries[i][1], 50000); + } + mdvc->white_point[0] = av_make_q(s->mdvc_white_point[0], 50000); + mdvc->white_point[1] = av_make_q(s->mdvc_white_point[1], 50000); + mdvc->has_luminance = 1; + mdvc->max_luminance = av_make_q(s->mdvc_max_lum, 10000); + mdvc->min_luminance = av_make_q(s->mdvc_min_lum, 10000); } - mdvc->white_point[0] = av_make_q(s->mdvc_white_point[0], 50000); - mdvc->white_point[1] = av_make_q(s->mdvc_white_point[1], 50000); - mdvc->has_luminance = 1; - mdvc->max_luminance = av_make_q(s->mdvc_max_lum, 10000); - mdvc->min_luminance = av_make_q(s->mdvc_min_lum, 10000); } return 0; diff --git a/libavcodec/qsvdec.c b/libavcodec/qsvdec.c index d688a17c41..4f39f6942a 100644 --- a/libavcodec/qsvdec.c +++ b/libavcodec/qsvdec.c @@ -651,42 +651,50 @@ static int qsv_export_film_grain(AVCodecContext *avctx, mfxExtAV1FilmGrainParam static int qsv_export_hdr_side_data(AVCodecContext *avctx, mfxExtMasteringDisplayColourVolume *mdcv, mfxExtContentLightLevelInfo *clli, AVFrame *frame) { + int ret; + // The SDK re-uses this flag for HDR SEI parsing if (mdcv->InsertPayloadToggle) { - AVMasteringDisplayMetadata *mastering = av_mastering_display_metadata_create_side_data(frame); + AVMasteringDisplayMetadata *mastering; const int mapping[3] = {2, 0, 1}; const int chroma_den = 50000; const int luma_den = 10000; int i; - if (!mastering) - return AVERROR(ENOMEM); + ret = ff_decode_mastering_display_new(avctx, frame, &mastering); + if (ret < 0) + return ret; - for (i = 0; i < 3; i++) { - const int j = mapping[i]; - mastering->display_primaries[i][0] = av_make_q(mdcv->DisplayPrimariesX[j], chroma_den); - mastering->display_primaries[i][1] = av_make_q(mdcv->DisplayPrimariesY[j], chroma_den); + if (mastering) { + for (i = 0; i < 3; i++) { + const int j = mapping[i]; + mastering->display_primaries[i][0] = av_make_q(mdcv->DisplayPrimariesX[j], chroma_den); + mastering->display_primaries[i][1] = av_make_q(mdcv->DisplayPrimariesY[j], chroma_den); + } + + mastering->white_point[0] = av_make_q(mdcv->WhitePointX, chroma_den); + mastering->white_point[1] = av_make_q(mdcv->WhitePointY, chroma_den); + + mastering->max_luminance = av_make_q(mdcv->MaxDisplayMasteringLuminance, luma_den); + mastering->min_luminance = av_make_q(mdcv->MinDisplayMasteringLuminance, luma_den); + + mastering->has_luminance = 1; + mastering->has_primaries = 1; } - - mastering->white_point[0] = av_make_q(mdcv->WhitePointX, chroma_den); - mastering->white_point[1] = av_make_q(mdcv->WhitePointY, chroma_den); - - mastering->max_luminance = av_make_q(mdcv->MaxDisplayMasteringLuminance, luma_den); - mastering->min_luminance = av_make_q(mdcv->MinDisplayMasteringLuminance, luma_den); - - mastering->has_luminance = 1; - mastering->has_primaries = 1; } // The SDK re-uses this flag for HDR SEI parsing if (clli->InsertPayloadToggle) { - AVContentLightMetadata *light = av_content_light_metadata_create_side_data(frame); + AVContentLightMetadata *light; - if (!light) - return AVERROR(ENOMEM); + ret = ff_decode_content_light_new(avctx, frame, &light); + if (ret < 0) + return ret; - light->MaxCLL = clli->MaxContentLightLevel; - light->MaxFALL = clli->MaxPicAverageLightLevel; + if (light) { + light->MaxCLL = clli->MaxContentLightLevel; + light->MaxFALL = clli->MaxPicAverageLightLevel; + } } return 0;