[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