[FFmpeg-devel] [PATCH] avcodec/options: Add options for inputing HDR10-related metadata
Paul B Mahol
onemda at gmail.com
Tue Aug 11 13:16:26 EEST 2020
I think this should use some sort of side data instead or adding new
fields to AVCodecContext.
On 8/11/20, Kenny McClive <kenny.mcclive at me.com> 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.
>
> 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".
More information about the ffmpeg-devel
mailing list