[FFmpeg-devel] [PATCH] avcodec/options: Add options for inputing HDR10-related metadata
lance.lmwang at gmail.com
lance.lmwang at gmail.com
Tue Aug 11 15:50:44 EEST 2020
On Mon, Aug 10, 2020 at 07:54:28PM -0600, Kenny McClive wrote:
> Previously, the only way to input the master display and content light metadata required for HDR10 was through x265-params. Obviously, that only worked with x265. If you wanted to use a different encoder like nvenc, you were out of luck. The options specified are written to the container (mov or matroska) only. Additional work would be required to write it to frames. The default values for the master display options may seem unorthodox, but it allows you to differentiate between 0 (which some movies use) and unspecified. The same was not done for content light metadata because 0 seems to mean unspecified in other systems such as x265.
>
Before I had submit a patchset to support HDR10 for nvenc, I'm using for
existing side data for master display. It's not accept for it's for nvenc only,
other developers want the function to be general for all encoder, so it's
preferable to add one bsf filter to support it. Refer to below link:
https://www.mail-archive.com/ffmpeg-devel@ffmpeg.org/msg84242.html
> Signed-off-by: Kenny McClive <kenny.mcclive at me.com>
> ---
> libavcodec/avcodec.h | 90 ++++++++++++++++++
> libavcodec/codec_par.h | 7 ++
> libavcodec/options_table.h | 12 +++
> libavcodec/utils.c | 134 ++++++++++++++++++++++++++-
> libavformat/matroskaenc.c | 62 ++++++++-----
> libavformat/movenc.c | 29 ++++--
> tests/ref/fate/api-mjpeg-codec-param | 24 +++++
> tests/ref/fate/api-png-codec-param | 24 +++++
> 8 files changed, 352 insertions(+), 30 deletions(-)
>
> diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
> index c91b2fd169..6f8b42b048 100644
> --- a/libavcodec/avcodec.h
> +++ b/libavcodec/avcodec.h
> @@ -411,6 +411,12 @@ typedef struct RcOverride{
> */
> #define AV_CODEC_EXPORT_DATA_VIDEO_ENC_PARAMS (1 << 2)
>
> +/**
> + * Encoding only.
> + * Indicates that a mastering display option was not specified.
> + */
> +#define AV_CODEC_MASTER_DISPLAY_UNSPECIFIED INT_MAX
> +
> /**
> * Pan Scan area.
> * This specifies the area which should be displayed.
> @@ -2352,6 +2358,90 @@ typedef struct AVCodecContext {
> * - encoding: set by user
> */
> int export_side_data;
> +
> + /**
> + * CIE 1931 x chromaticity coord of red color primary for mastering display.
> + * - encoding: Set by user
> + * - decoding: unused
> + */
> + AVRational master_display_red_x;
> +
> + /**
> + * CIE 1931 y chromaticity coord of red color primary for mastering display.
> + * - encoding: Set by user
> + * - decoding: unused
> + */
> + AVRational master_display_red_y;
> +
> + /**
> + * CIE 1931 x chromaticity coord of green color primary for mastering display.
> + * - encoding: Set by user
> + * - decoding: unused
> + */
> + AVRational master_display_green_x;
> +
> + /**
> + * CIE 1931 y chromaticity coord of green color primary for mastering display.
> + * - encoding: Set by user
> + * - decoding: unused
> + */
> + AVRational master_display_green_y;
> +
> + /**
> + * CIE 1931 x chromaticity coord of blue color primary for mastering display.
> + * - encoding: Set by user
> + * - decoding: unused
> + */
> + AVRational master_display_blue_x;
> +
> + /**
> + * CIE 1931 y chromaticity coord of blue color primary for mastering display.
> + * - encoding: Set by user
> + * - decoding: unused
> + */
> + AVRational master_display_blue_y;
> +
> + /**
> + * CIE 1931 x chromaticity coord of white point for mastering display.
> + * - encoding: Set by user
> + * - decoding: unused
> + */
> + AVRational master_display_white_x;
> +
> + /**
> + * CIE 1931 y chromaticity coord of white point for mastering display.
> + * - encoding: Set by user
> + * - decoding: unused
> + */
> + AVRational master_display_white_y;
> +
> + /**
> + * Min luminance of mastering display (cd/m^2).
> + * - encoding: Set by user
> + * - decoding: unused
> + */
> + AVRational master_display_min_luminance;
> +
> + /**
> + * Max luminance of mastering display (cd/m^2).
> + * - encoding: Set by user
> + * - decoding: unused
> + */
> + AVRational master_display_max_luminance;
> +
> + /**
> + * Max content light level (cd/m^2).
> + * - encoding: Set by user
> + * - decoding: unused
> + */
> + unsigned max_cll;
> +
> + /**
> + * Max average light level per frame (cd/m^2).
> + * - encoding: Set by user
> + * - decoding: unused
> + */
> + unsigned max_fall;
> } AVCodecContext;
>
> #if FF_API_CODEC_GET_SET
> diff --git a/libavcodec/codec_par.h b/libavcodec/codec_par.h
> index 948758e237..fe1fe3861b 100644
> --- a/libavcodec/codec_par.h
> +++ b/libavcodec/codec_par.h
> @@ -24,6 +24,7 @@
> #include <stdint.h>
>
> #include "libavutil/avutil.h"
> +#include "libavutil/mastering_display_metadata.h"
> #include "libavutil/rational.h"
> #include "libavutil/pixfmt.h"
>
> @@ -149,6 +150,12 @@ typedef struct AVCodecParameters {
> enum AVColorSpace color_space;
> enum AVChromaLocation chroma_location;
>
> + /**
> + * Video only. HDR metadata.
> + */
> + AVMasteringDisplayMetadata master_display_metadata;
> + AVContentLightMetadata content_light_metadata;
> +
> /**
> * Video only. Number of delayed frames.
> */
> diff --git a/libavcodec/options_table.h b/libavcodec/options_table.h
> index 1d0db1b5a4..5c1cfc77b4 100644
> --- a/libavcodec/options_table.h
> +++ b/libavcodec/options_table.h
> @@ -412,6 +412,18 @@ static const AVOption avcodec_options[] = {
> {"bottomleft", "Bottom-left", 0, AV_OPT_TYPE_CONST, {.i64 = AVCHROMA_LOC_BOTTOMLEFT }, INT_MIN, INT_MAX, V|E|D, "chroma_sample_location_type"},
> {"bottom", "Bottom", 0, AV_OPT_TYPE_CONST, {.i64 = AVCHROMA_LOC_BOTTOM }, INT_MIN, INT_MAX, V|E|D, "chroma_sample_location_type"},
> {"unspecified", "Unspecified", 0, AV_OPT_TYPE_CONST, {.i64 = AVCHROMA_LOC_UNSPECIFIED }, INT_MIN, INT_MAX, V|E|D, "chroma_sample_location_type"},
> +{"master_display_red_x", "mastering display x chromaticity coord for red color primary", OFFSET(master_display_red_x), AV_OPT_TYPE_RATIONAL, {.dbl = AV_CODEC_MASTER_DISPLAY_UNSPECIFIED}, 0, INT_MAX, V|E},
> +{"master_display_red_y", "mastering display y chromaticity coord for red color primary", OFFSET(master_display_red_y), AV_OPT_TYPE_RATIONAL, {.dbl = AV_CODEC_MASTER_DISPLAY_UNSPECIFIED}, 0, INT_MAX, V|E},
> +{"master_display_green_x", "mastering display x chromaticity coord for green color primary", OFFSET(master_display_green_x), AV_OPT_TYPE_RATIONAL, {.dbl = AV_CODEC_MASTER_DISPLAY_UNSPECIFIED}, 0, INT_MAX, V|E},
> +{"master_display_green_y", "mastering display y chromaticity coord for green color primary", OFFSET(master_display_green_y), AV_OPT_TYPE_RATIONAL, {.dbl = AV_CODEC_MASTER_DISPLAY_UNSPECIFIED}, 0, INT_MAX, V|E},
> +{"master_display_blue_x", "mastering display x chromaticity coord for blue color primary", OFFSET(master_display_blue_x), AV_OPT_TYPE_RATIONAL, {.dbl = AV_CODEC_MASTER_DISPLAY_UNSPECIFIED}, 0, INT_MAX, V|E},
> +{"master_display_blue_y", "mastering display y chromaticity coord for blue color primary", OFFSET(master_display_blue_y), AV_OPT_TYPE_RATIONAL, {.dbl = AV_CODEC_MASTER_DISPLAY_UNSPECIFIED}, 0, INT_MAX, V|E},
> +{"master_display_white_x", "mastering display x chromaticity coord for white point", OFFSET(master_display_white_x), AV_OPT_TYPE_RATIONAL, {.dbl = AV_CODEC_MASTER_DISPLAY_UNSPECIFIED}, 0, INT_MAX, V|E},
> +{"master_display_white_y", "mastering display y chromaticity coord for white point", OFFSET(master_display_white_y), AV_OPT_TYPE_RATIONAL, {.dbl = AV_CODEC_MASTER_DISPLAY_UNSPECIFIED}, 0, INT_MAX, V|E},
> +{"master_display_min_lum", "mastering display min luminance", OFFSET(master_display_min_luminance), AV_OPT_TYPE_RATIONAL, {.dbl = AV_CODEC_MASTER_DISPLAY_UNSPECIFIED}, 0, INT_MAX, V|E},
> +{"master_display_max_lum", "mastering display max luminance", OFFSET(master_display_max_luminance), AV_OPT_TYPE_RATIONAL, {.dbl = AV_CODEC_MASTER_DISPLAY_UNSPECIFIED}, 0, INT_MAX, V|E},
> +{"max_cll", "max content light level", OFFSET(max_cll), AV_OPT_TYPE_INT64, {.i64 = DEFAULT }, 0, INT_MAX, V|E},
> +{"max_fall", "max frame average light level", OFFSET(max_fall), AV_OPT_TYPE_INT64, {.i64 = DEFAULT }, 0, INT_MAX, V|E},
> {"log_level_offset", "set the log level offset", OFFSET(log_level_offset), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX },
> {"slices", "set the number of slices, used in parallelized encoding", OFFSET(slices), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, V|E},
> {"thread_type", "select multithreading type", OFFSET(thread_type), AV_OPT_TYPE_FLAGS, {.i64 = FF_THREAD_SLICE|FF_THREAD_FRAME }, 0, INT_MAX, V|A|E|D, "thread_type"},
> diff --git a/libavcodec/utils.c b/libavcodec/utils.c
> index 5a2a90b030..ef90ad0513 100644
> --- a/libavcodec/utils.c
> +++ b/libavcodec/utils.c
> @@ -35,6 +35,7 @@
> #include "libavutil/frame.h"
> #include "libavutil/hwcontext.h"
> #include "libavutil/internal.h"
> +#include "libavutil/mastering_display_metadata.h"
> #include "libavutil/mathematics.h"
> #include "libavutil/mem_internal.h"
> #include "libavutil/pixdesc.h"
> @@ -66,7 +67,7 @@
> #include "libavutil/ffversion.h"
> const char av_codec_ffversion[] = "FFmpeg version " FFMPEG_VERSION;
>
> -static AVMutex codec_mutex = AV_MUTEX_INITIALIZER;
> +static AVMutex codec_mutex = AV_MUTEX_INITIALIZER;
>
> void av_fast_padded_malloc(void *ptr, unsigned int *size, size_t min_size)
> {
> @@ -2031,6 +2032,34 @@ AVCPBProperties *ff_add_cpb_side_data(AVCodecContext *avctx)
> return props;
> }
>
> +static void master_display_metadata_reset(AVMasteringDisplayMetadata *metadata)
> +{
> + if (!metadata)
> + return;
> +
> + metadata->display_primaries[0][0] = (AVRational){ 0, 1 };
> + metadata->display_primaries[0][1] = (AVRational){ 0, 1 };
> + metadata->display_primaries[1][0] = (AVRational){ 0, 1 };
> + metadata->display_primaries[1][1] = (AVRational){ 0, 1 };
> + metadata->display_primaries[2][0] = (AVRational){ 0, 1 };
> + metadata->display_primaries[2][1] = (AVRational){ 0, 1 };
> + metadata->white_point[0] = (AVRational){ 0, 1 };
> + metadata->white_point[1] = (AVRational){ 0, 1 };
> + metadata->has_primaries = 0;
> + metadata->min_luminance = (AVRational){ 0, 1 };
> + metadata->max_luminance = (AVRational){ 0, 1 };
> + metadata->has_luminance = 0;
> +}
> +
> +static void content_light_metadata_reset(AVContentLightMetadata *metadata)
> +{
> + if (!metadata)
> + return;
> +
> + metadata->MaxCLL = 0;
> + metadata->MaxFALL = 0;
> +}
> +
> static void codec_parameters_reset(AVCodecParameters *par)
> {
> av_freep(&par->extradata);
> @@ -2049,6 +2078,9 @@ static void codec_parameters_reset(AVCodecParameters *par)
> par->sample_aspect_ratio = (AVRational){ 0, 1 };
> par->profile = FF_PROFILE_UNKNOWN;
> par->level = FF_LEVEL_UNKNOWN;
> +
> + master_display_metadata_reset(&par->master_display_metadata);
> + content_light_metadata_reset(&par->content_light_metadata);
> }
>
> AVCodecParameters *avcodec_parameters_alloc(void)
> @@ -2090,6 +2122,53 @@ int avcodec_parameters_copy(AVCodecParameters *dst, const AVCodecParameters *src
> return 0;
> }
>
> +static void mastering_display_metadata_from_context(AVMasteringDisplayMetadata *metadata,
> + const AVCodecContext *codec)
> +{
> + if (!metadata || !codec)
> + return;
> +
> + master_display_metadata_reset(metadata);
> +
> + if (codec->master_display_red_x.num != AV_CODEC_MASTER_DISPLAY_UNSPECIFIED &&
> + codec->master_display_red_y.num != AV_CODEC_MASTER_DISPLAY_UNSPECIFIED &&
> + codec->master_display_green_x.num != AV_CODEC_MASTER_DISPLAY_UNSPECIFIED &&
> + codec->master_display_green_y.num != AV_CODEC_MASTER_DISPLAY_UNSPECIFIED &&
> + codec->master_display_blue_x.num != AV_CODEC_MASTER_DISPLAY_UNSPECIFIED &&
> + codec->master_display_blue_y.num != AV_CODEC_MASTER_DISPLAY_UNSPECIFIED &&
> + codec->master_display_white_x.num != AV_CODEC_MASTER_DISPLAY_UNSPECIFIED &&
> + codec->master_display_white_y.num != AV_CODEC_MASTER_DISPLAY_UNSPECIFIED)
> + {
> + metadata->display_primaries[0][0] = codec->master_display_red_x;
> + metadata->display_primaries[0][1] = codec->master_display_red_y;
> + metadata->display_primaries[1][0] = codec->master_display_green_x;
> + metadata->display_primaries[1][1] = codec->master_display_green_y;
> + metadata->display_primaries[2][0] = codec->master_display_blue_x;
> + metadata->display_primaries[2][1] = codec->master_display_blue_y;
> + metadata->white_point[0] = codec->master_display_white_x;
> + metadata->white_point[1] = codec->master_display_white_y;
> + metadata->has_primaries = 1;
> + }
> +
> + if (codec->master_display_min_luminance.den > 0 &&
> + codec->master_display_max_luminance.den > 0)
> + {
> + metadata->min_luminance = codec->master_display_min_luminance;
> + metadata->max_luminance = codec->master_display_max_luminance;
> + metadata->has_luminance = 1;
> + }
> +}
> +
> +static void content_light_metadata_from_context(AVContentLightMetadata *metadata,
> + const AVCodecContext *codec)
> +{
> + if (!metadata || !codec)
> + return;
> +
> + metadata->MaxCLL = codec->max_cll;
> + metadata->MaxFALL = codec->max_fall;
> +}
> +
> int avcodec_parameters_from_context(AVCodecParameters *par,
> const AVCodecContext *codec)
> {
> @@ -2118,6 +2197,9 @@ int avcodec_parameters_from_context(AVCodecParameters *par,
> par->chroma_location = codec->chroma_sample_location;
> par->sample_aspect_ratio = codec->sample_aspect_ratio;
> par->video_delay = codec->has_b_frames;
> +
> + mastering_display_metadata_from_context(&par->master_display_metadata, codec);
> + content_light_metadata_from_context(&par->content_light_metadata, codec);
> break;
> case AVMEDIA_TYPE_AUDIO:
> par->format = codec->sample_fmt;
> @@ -2147,6 +2229,53 @@ int avcodec_parameters_from_context(AVCodecParameters *par,
> return 0;
> }
>
> +static void mastering_display_metadata_to_context(AVCodecContext *codec,
> + const AVMasteringDisplayMetadata *metadata)
> +{
> + if (!codec || !metadata)
> + return;
> +
> + if (metadata->has_primaries)
> + {
> + codec->master_display_red_x = metadata->display_primaries[0][0];
> + codec->master_display_red_y = metadata->display_primaries[0][1];
> + codec->master_display_green_x = metadata->display_primaries[1][0];
> + codec->master_display_green_y = metadata->display_primaries[1][1];
> + codec->master_display_blue_x = metadata->display_primaries[2][0];
> + codec->master_display_blue_y = metadata->display_primaries[2][1];
> + codec->master_display_white_x = metadata->white_point[0];
> + codec->master_display_white_y = metadata->white_point[1];
> + } else {
> + codec->master_display_red_x = (AVRational){ AV_CODEC_MASTER_DISPLAY_UNSPECIFIED, 1 };
> + codec->master_display_red_y = (AVRational){ AV_CODEC_MASTER_DISPLAY_UNSPECIFIED, 1 };
> + codec->master_display_green_x = (AVRational){ AV_CODEC_MASTER_DISPLAY_UNSPECIFIED, 1 };
> + codec->master_display_green_y = (AVRational){ AV_CODEC_MASTER_DISPLAY_UNSPECIFIED, 1 };
> + codec->master_display_blue_x = (AVRational){ AV_CODEC_MASTER_DISPLAY_UNSPECIFIED, 1 };
> + codec->master_display_blue_y = (AVRational){ AV_CODEC_MASTER_DISPLAY_UNSPECIFIED, 1 };
> + codec->master_display_white_x = (AVRational){ AV_CODEC_MASTER_DISPLAY_UNSPECIFIED, 1 };
> + codec->master_display_white_y = (AVRational){ AV_CODEC_MASTER_DISPLAY_UNSPECIFIED, 1 };
> + }
> +
> + if (metadata->has_luminance)
> + {
> + codec->master_display_min_luminance = metadata->min_luminance;
> + codec->master_display_max_luminance = metadata->max_luminance;
> + } else {
> + codec->master_display_min_luminance = (AVRational){ AV_CODEC_MASTER_DISPLAY_UNSPECIFIED, 1 };
> + codec->master_display_max_luminance = (AVRational){ AV_CODEC_MASTER_DISPLAY_UNSPECIFIED, 1 };
> + }
> +}
> +
> +static void content_light_metadata_to_context(AVCodecContext *codec,
> + const AVContentLightMetadata *metadata)
> +{
> + if (!codec || !metadata)
> + return;
> +
> + codec->max_cll = metadata->MaxCLL;
> + codec->max_fall = metadata->MaxFALL;
> +}
> +
> int avcodec_parameters_to_context(AVCodecContext *codec,
> const AVCodecParameters *par)
> {
> @@ -2173,6 +2302,9 @@ int avcodec_parameters_to_context(AVCodecContext *codec,
> codec->chroma_sample_location = par->chroma_location;
> codec->sample_aspect_ratio = par->sample_aspect_ratio;
> codec->has_b_frames = par->video_delay;
> +
> + mastering_display_metadata_to_context(codec, &par->master_display_metadata);
> + content_light_metadata_to_context(codec, &par->content_light_metadata);
> break;
> case AVMEDIA_TYPE_AUDIO:
> codec->sample_fmt = par->format;
> diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c
> index 233c472b8f..dfe9d45f6f 100644
> --- a/libavformat/matroskaenc.c
> +++ b/libavformat/matroskaenc.c
> @@ -869,43 +869,61 @@ static void mkv_write_video_color(AVIOContext *pb, const AVStream *st,
> put_ebml_uint(dyn_cp, MATROSKA_ID_VIDEOCOLORCHROMASITINGVERT, (ypos >> 7) + 1);
> }
>
> - side_data = av_stream_get_side_data(st, AV_PKT_DATA_CONTENT_LIGHT_LEVEL,
> - NULL);
> - if (side_data) {
> - const AVContentLightMetadata *metadata = side_data;
> - put_ebml_uint(dyn_cp, MATROSKA_ID_VIDEOCOLORMAXCLL, metadata->MaxCLL);
> - put_ebml_uint(dyn_cp, MATROSKA_ID_VIDEOCOLORMAXFALL, metadata->MaxFALL);
> + const AVContentLightMetadata *content_light_metadata = &par->content_light_metadata;
> +
> + if (content_light_metadata->MaxCLL <= 0 || content_light_metadata->MaxFALL <= 0) {
> + side_data = av_stream_get_side_data(st, AV_PKT_DATA_CONTENT_LIGHT_LEVEL,
> + NULL);
> + if (side_data) {
> + content_light_metadata = side_data;
> + } else {
> + content_light_metadata = NULL;
> + }
> + }
> +
> + if (content_light_metadata) {
> + put_ebml_uint(dyn_cp, MATROSKA_ID_VIDEOCOLORMAXCLL, content_light_metadata->MaxCLL);
> + put_ebml_uint(dyn_cp, MATROSKA_ID_VIDEOCOLORMAXFALL, content_light_metadata->MaxFALL);
> }
>
> - side_data = av_stream_get_side_data(st, AV_PKT_DATA_MASTERING_DISPLAY_METADATA,
> - NULL);
> - if (side_data) {
> + const AVMasteringDisplayMetadata *master_display_metadata = &par->master_display_metadata;
> +
> + if (!master_display_metadata->has_primaries || !master_display_metadata->has_luminance) {
> + side_data = av_stream_get_side_data(st, AV_PKT_DATA_MASTERING_DISPLAY_METADATA,
> + NULL);
> + if (side_data) {
> + master_display_metadata = side_data;
> + } else {
> + master_display_metadata = NULL;
> + }
> + }
> +
> + if (master_display_metadata) {
> ebml_master meta_element = start_ebml_master(
> dyn_cp, MATROSKA_ID_VIDEOCOLORMASTERINGMETA, 10 * (2 + 1 + 8));
> - const AVMasteringDisplayMetadata *metadata = side_data;
> - if (metadata->has_primaries) {
> + if (master_display_metadata->has_primaries) {
> put_ebml_float(dyn_cp, MATROSKA_ID_VIDEOCOLOR_RX,
> - av_q2d(metadata->display_primaries[0][0]));
> + av_q2d(master_display_metadata->display_primaries[0][0]));
> put_ebml_float(dyn_cp, MATROSKA_ID_VIDEOCOLOR_RY,
> - av_q2d(metadata->display_primaries[0][1]));
> + av_q2d(master_display_metadata->display_primaries[0][1]));
> put_ebml_float(dyn_cp, MATROSKA_ID_VIDEOCOLOR_GX,
> - av_q2d(metadata->display_primaries[1][0]));
> + av_q2d(master_display_metadata->display_primaries[1][0]));
> put_ebml_float(dyn_cp, MATROSKA_ID_VIDEOCOLOR_GY,
> - av_q2d(metadata->display_primaries[1][1]));
> + av_q2d(master_display_metadata->display_primaries[1][1]));
> put_ebml_float(dyn_cp, MATROSKA_ID_VIDEOCOLOR_BX,
> - av_q2d(metadata->display_primaries[2][0]));
> + av_q2d(master_display_metadata->display_primaries[2][0]));
> put_ebml_float(dyn_cp, MATROSKA_ID_VIDEOCOLOR_BY,
> - av_q2d(metadata->display_primaries[2][1]));
> + av_q2d(master_display_metadata->display_primaries[2][1]));
> put_ebml_float(dyn_cp, MATROSKA_ID_VIDEOCOLOR_WHITEX,
> - av_q2d(metadata->white_point[0]));
> + av_q2d(master_display_metadata->white_point[0]));
> put_ebml_float(dyn_cp, MATROSKA_ID_VIDEOCOLOR_WHITEY,
> - av_q2d(metadata->white_point[1]));
> + av_q2d(master_display_metadata->white_point[1]));
> }
> - if (metadata->has_luminance) {
> + if (master_display_metadata->has_luminance) {
> put_ebml_float(dyn_cp, MATROSKA_ID_VIDEOCOLOR_LUMINANCEMAX,
> - av_q2d(metadata->max_luminance));
> + av_q2d(master_display_metadata->max_luminance));
> put_ebml_float(dyn_cp, MATROSKA_ID_VIDEOCOLOR_LUMINANCEMIN,
> - av_q2d(metadata->min_luminance));
> + av_q2d(master_display_metadata->min_luminance));
> }
> end_ebml_master(dyn_cp, meta_element);
> }
> diff --git a/libavformat/movenc.c b/libavformat/movenc.c
> index 7db2e28840..074c463cee 100644
> --- a/libavformat/movenc.c
> +++ b/libavformat/movenc.c
> @@ -1947,14 +1947,21 @@ static int mov_write_colr_tag(AVIOContext *pb, MOVTrack *track, int prefer_icc)
> static int mov_write_clli_tag(AVIOContext *pb, MOVTrack *track)
> {
> const uint8_t *side_data;
> - const AVContentLightMetadata *content_light_metadata;
> + const AVContentLightMetadata *content_light_metadata = &track->par->content_light_metadata;
>
> - side_data = av_stream_get_side_data(track->st, AV_PKT_DATA_CONTENT_LIGHT_LEVEL, NULL);
> - if (!side_data) {
> + if (content_light_metadata->MaxCLL <= 0 || content_light_metadata->MaxFALL <= 0) {
> + side_data = av_stream_get_side_data(track->st, AV_PKT_DATA_CONTENT_LIGHT_LEVEL, NULL);
> + if (side_data) {
> + content_light_metadata = (const AVContentLightMetadata*)side_data;
> + } else {
> + content_light_metadata = NULL;
> + }
> + }
> +
> + if (!content_light_metadata) {
> av_log(NULL, AV_LOG_VERBOSE, "Not writing 'clli' atom. No content light level info.\n");
> return 0;
> }
> - content_light_metadata = (const AVContentLightMetadata*)side_data;
>
> avio_wb32(pb, 12); // size
> ffio_wfourcc(pb, "clli");
> @@ -1973,10 +1980,18 @@ static int mov_write_mdcv_tag(AVIOContext *pb, MOVTrack *track)
> const int chroma_den = 50000;
> const int luma_den = 10000;
> const uint8_t *side_data;
> - const AVMasteringDisplayMetadata *metadata;
> + const AVMasteringDisplayMetadata *metadata = &track->par->master_display_metadata;
>
> - side_data = av_stream_get_side_data(track->st, AV_PKT_DATA_MASTERING_DISPLAY_METADATA, NULL);
> - metadata = (const AVMasteringDisplayMetadata*)side_data;
> + if (!metadata->has_primaries || !metadata->has_luminance) {
> + side_data = av_stream_get_side_data(track->st, AV_PKT_DATA_MASTERING_DISPLAY_METADATA, NULL);
> +
> + if (side_data) {
> + metadata = (const AVMasteringDisplayMetadata*)side_data;
> + } else {
> + metadata = NULL;
> + }
> + }
> +
> if (!metadata || !metadata->has_primaries || !metadata->has_luminance) {
> av_log(NULL, AV_LOG_VERBOSE, "Not writing 'mdcv' atom. Missing mastering metadata.\n");
> return 0;
> diff --git a/tests/ref/fate/api-mjpeg-codec-param b/tests/ref/fate/api-mjpeg-codec-param
> index 82e3313aa9..48a28aa4e4 100644
> --- a/tests/ref/fate/api-mjpeg-codec-param
> +++ b/tests/ref/fate/api-mjpeg-codec-param
> @@ -118,6 +118,18 @@ stream=0, decode=0
> colorspace=5
> color_range=2
> chroma_sample_location=2
> + master_display_red_x=2147483647/1
> + master_display_red_y=2147483647/1
> + master_display_green_x=2147483647/1
> + master_display_green_y=2147483647/1
> + master_display_blue_x=2147483647/1
> + master_display_blue_y=2147483647/1
> + master_display_white_x=2147483647/1
> + master_display_white_y=2147483647/1
> + master_display_min_lum=2147483647/1
> + master_display_max_lum=2147483647/1
> + max_cll=0
> + max_fall=0
> log_level_offset=0
> slices=0
> thread_type=0x00000003
> @@ -261,6 +273,18 @@ stream=0, decode=1
> colorspace=5
> color_range=2
> chroma_sample_location=2
> + master_display_red_x=2147483647/1
> + master_display_red_y=2147483647/1
> + master_display_green_x=2147483647/1
> + master_display_green_y=2147483647/1
> + master_display_blue_x=2147483647/1
> + master_display_blue_y=2147483647/1
> + master_display_white_x=2147483647/1
> + master_display_white_y=2147483647/1
> + master_display_min_lum=2147483647/1
> + master_display_max_lum=2147483647/1
> + max_cll=0
> + max_fall=0
> log_level_offset=0
> slices=0
> thread_type=0x00000003
> diff --git a/tests/ref/fate/api-png-codec-param b/tests/ref/fate/api-png-codec-param
> index 7adaa5260d..84d5ae722b 100644
> --- a/tests/ref/fate/api-png-codec-param
> +++ b/tests/ref/fate/api-png-codec-param
> @@ -118,6 +118,18 @@ stream=0, decode=0
> colorspace=2
> color_range=2
> chroma_sample_location=0
> + master_display_red_x=2147483647/1
> + master_display_red_y=2147483647/1
> + master_display_green_x=2147483647/1
> + master_display_green_y=2147483647/1
> + master_display_blue_x=2147483647/1
> + master_display_blue_y=2147483647/1
> + master_display_white_x=2147483647/1
> + master_display_white_y=2147483647/1
> + master_display_min_lum=2147483647/1
> + master_display_max_lum=2147483647/1
> + max_cll=0
> + max_fall=0
> log_level_offset=0
> slices=0
> thread_type=0x00000003
> @@ -261,6 +273,18 @@ stream=0, decode=1
> colorspace=2
> color_range=2
> chroma_sample_location=0
> + master_display_red_x=2147483647/1
> + master_display_red_y=2147483647/1
> + master_display_green_x=2147483647/1
> + master_display_green_y=2147483647/1
> + master_display_blue_x=2147483647/1
> + master_display_blue_y=2147483647/1
> + master_display_white_x=2147483647/1
> + master_display_white_y=2147483647/1
> + master_display_min_lum=2147483647/1
> + master_display_max_lum=2147483647/1
> + max_cll=0
> + max_fall=0
> log_level_offset=0
> slices=0
> thread_type=0x00000003
> --
> 2.28.0
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request at ffmpeg.org with subject "unsubscribe".
--
Thanks,
Limin Wang
More information about the ffmpeg-devel
mailing list