From patchwork Tue Aug 11 01:54:28 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kenny McClive X-Patchwork-Id: 21596 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id A4E2644A662 for ; Tue, 11 Aug 2020 04:54:37 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 7E43D68A107; Tue, 11 Aug 2020 04:54:37 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from ms11p00im-qufo17281501.me.com (ms11p00im-qufo17281501.me.com [17.58.38.52]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 0DBD76880F0 for ; Tue, 11 Aug 2020 04:54:31 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=me.com; s=1a1hai; t=1597110869; bh=VCq98BX+lVNHi0yU402+tUU40j1GcejZzoNbKM10J+A=; h=From:Content-Type:Mime-Version:Subject:Message-Id:Date:To; b=u2kF1Jhim/U+9b3m86ZBN/EUoh9Mg6IEhhhVG7O/7UHRa9OCJhRp3SNQhV9y37wUC +kxJeWSHqzl0O0UWt8g7T26j9D1nOwj9JmfxX0XjJb9dlc7VOCp4n/ayL4dO6kCuoD e+wZknK9Ce2Sh9QojHwRCi9c3Ufp85NAVIlDiVWqCnuroHBWky3LTxDjNoxrqaOKGg L5KEydSQdkBOrYP+vxkhyXR/2wgTmOR4KPIC6d5da4wdt/sOzWr8CZ+KgDKS6a62nb cNuW+PdT5tUQDnhNqA32uiUra0UxVDhpSwPmsKoyfn9rfKLMjSByGPK9FZ+5O2NVue u56Tni4BLBg6Q== Received: from [10.0.1.2] (c-24-9-115-65.hsd1.co.comcast.net [24.9.115.65]) by ms11p00im-qufo17281501.me.com (Postfix) with ESMTPSA id D34EDB40202 for ; Tue, 11 Aug 2020 01:54:28 +0000 (UTC) From: Kenny McClive Mime-Version: 1.0 (Mac OS X Mail 13.0 \(3608.60.0.2.5\)) Message-Id: Date: Mon, 10 Aug 2020 19:54:28 -0600 To: ffmpeg-devel@ffmpeg.org X-Mailer: Apple Mail (2.3608.60.0.2.5) X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.235, 18.0.687 definitions=2020-08-11_01:2020-08-06, 2020-08-11 signatures=0 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 suspectscore=1 malwarescore=0 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 mlxscore=0 mlxlogscore=999 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-2004280000 definitions=main-2008110012 Subject: [FFmpeg-devel] [PATCH] avcodec/options: Add options for inputing HDR10-related metadata X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" 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 --- 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 #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