From patchwork Mon Aug 31 19:07:55 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Harry Mallon X-Patchwork-Id: 22029 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 BE5E2449B8A for ; Mon, 31 Aug 2020 22:08:11 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id A4F5C68AA7F; Mon, 31 Aug 2020 22:08:11 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wr1-f51.google.com (mail-wr1-f51.google.com [209.85.221.51]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id DFFB068037C for ; Mon, 31 Aug 2020 22:08:05 +0300 (EEST) Received: by mail-wr1-f51.google.com with SMTP id c15so6972054wrs.11 for ; Mon, 31 Aug 2020 12:08:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=codex.online; s=google; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=tPXdtgXEM0RiQhGplF3QCwbHGb3seiKNIgT9cHdZ7oI=; b=CqrWRfoYBPHwii6ItLzlpohx3hKG4ZahDDNgiHOfQfVf9Q4E/qkjwaiHkur9Dpn5i1 xVoGhkX3uhvYmpIbbzNhP+P+FzW161lMrV0ajNbuaf8WdH80YEwKNYFRupQtTnFLyjc1 fzZLUNHXgyTa8eX5N/fzGYb5xdFVbE97xqu6w= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=tPXdtgXEM0RiQhGplF3QCwbHGb3seiKNIgT9cHdZ7oI=; b=YEnlAV3yIhMBXMVXGtz4PuMt7lKLzW2NvJsZZtULWEgirSCJcb17ue8XPCGT8cngP4 DLbFkAav7aEfS9GNjoTOWtvYHJKPTNBQvosbGpGf0Up2Cd2C+b8BGpmBBtPDcC9iCHki tQ9lTFdj7xBcY02jOmp5qay44IvJqH8MOEWCFA2F1CB1g3RWevWjzOXQYX1/h1z8mBhU fh1MCno87hxeIC5cniF4FChuVuFvof5CJRqZN4zrCp8llidjsxrggXfgBprFKvOo1py7 feVkx0BzGYzxo7Sn90wJ2EPi0eEcA7Odks9SR2DxJ4fk9KVm/w75aRzHsGKe2ijqQ8I+ BieQ== X-Gm-Message-State: AOAM530d6o7HDpnsUe53SfpOH2B0ht4vpNpGN8XuV7pnhl4GRypemqmD 9Ool2mY02NKHuLf0l9fTMAXxAHN55Y/HfA== X-Google-Smtp-Source: ABdhPJw0PcVCYw4gTJ9xgiX0y1K/u8AN2m3xMIjNtMxvWcQiEbocOdGpvmQUDb1x27u+Q1+FbzWj/Q== X-Received: by 2002:a5d:5306:: with SMTP id e6mr2971866wrv.156.1598900884941; Mon, 31 Aug 2020 12:08:04 -0700 (PDT) Received: from localhost ([2a01:4b00:8571:3800:dc8b:96b6:bc7:b353]) by smtp.gmail.com with ESMTPSA id b14sm13226407wrj.93.2020.08.31.12.08.04 for (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Mon, 31 Aug 2020 12:08:04 -0700 (PDT) From: Harry Mallon To: ffmpeg-devel@ffmpeg.org Date: Mon, 31 Aug 2020 20:07:55 +0100 Message-Id: <20200831190756.80515-2-harry.mallon@codex.online> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20200831190756.80515-1-harry.mallon@codex.online> References: <20200831190756.80515-1-harry.mallon@codex.online> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 2/3] avformat/mxfenc: Write Mastering Display Colour Volume to MXF 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" Described in Annex B SMPTE ST 2067-21:2020 Signed-off-by: Harry Mallon --- libavformat/mxfenc.c | 56 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/libavformat/mxfenc.c b/libavformat/mxfenc.c index e495b5ba0e..fe1ecb6705 100644 --- a/libavformat/mxfenc.c +++ b/libavformat/mxfenc.c @@ -44,6 +44,7 @@ #include "libavutil/random_seed.h" #include "libavutil/timecode.h" #include "libavutil/avassert.h" +#include "libavutil/mastering_display_metadata.h" #include "libavutil/pixdesc.h" #include "libavutil/time_internal.h" #include "libavcodec/bytestream.h" @@ -421,6 +422,13 @@ static const MXFLocalTagPair mxf_user_comments_local_tag[] = { { 0x5003, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x03,0x02,0x01,0x02,0x0A,0x01,0x00,0x00}}, /* Value */ }; +static const MXFLocalTagPair mxf_mastering_display_local_tags[] = { + { 0x8201, {0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x04,0x20,0x04,0x01,0x01,0x01,0x00,0x00}}, /* Mastering Display Primaries */ + { 0x8202, {0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x04,0x20,0x04,0x01,0x01,0x02,0x00,0x00}}, /* Mastering Display White Point Chromaticity */ + { 0x8203, {0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x04,0x20,0x04,0x01,0x01,0x03,0x00,0x00}}, /* Mastering Display Maximum Luminance */ + { 0x8204, {0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x04,0x20,0x04,0x01,0x01,0x04,0x00,0x00}}, /* Mastering Display Minimum Luminance */ +}; + static void mxf_write_uuid(AVIOContext *pb, enum MXFMetadataSetType type, int value) { avio_write(pb, uuid_base, 12); @@ -510,6 +518,7 @@ static void mxf_write_primer_pack(AVFormatContext *s) AVIOContext *pb = s->pb; int local_tag_number, i = 0; int avc_tags_count = 0; + int mastering_tags_count = 0; local_tag_number = FF_ARRAY_ELEMS(mxf_local_tag_batch); local_tag_number += mxf->store_user_comments * FF_ARRAY_ELEMS(mxf_user_comments_local_tag); @@ -522,6 +531,15 @@ static void mxf_write_primer_pack(AVFormatContext *s) } } + for (i = 0; i < s->nb_streams; i++) { + uint8_t *side_data = av_stream_get_side_data(s->streams[i], AV_PKT_DATA_MASTERING_DISPLAY_METADATA, NULL); + if (side_data) { + mastering_tags_count = FF_ARRAY_ELEMS(mxf_mastering_display_local_tags); + local_tag_number += mastering_tags_count; + break; + } + } + avio_write(pb, primer_pack_key, 16); klv_encode_ber_length(pb, local_tag_number * 18 + 8); @@ -539,6 +557,8 @@ static void mxf_write_primer_pack(AVFormatContext *s) } if (avc_tags_count > 0) mxf_write_local_tags(pb, mxf_avc_subdescriptor_local_tags, avc_tags_count); + if (mastering_tags_count > 0) + mxf_write_local_tags(pb, mxf_mastering_display_local_tags, mastering_tags_count); } static void mxf_write_local_tag(AVIOContext *pb, int size, int tag) @@ -1048,6 +1068,11 @@ static const UID mxf_generic_sound_descriptor_key = { 0x06,0x0E,0x2B,0x34,0x02,0 static const UID mxf_avc_subdescriptor_key = { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x6E,0x00 }; +static inline int64_t rescale_mastering(AVRational q, int b) +{ + return av_rescale(q.num, b, q.den); +} + static int64_t mxf_write_cdci_common(AVFormatContext *s, AVStream *st, const UID key) { MXFStreamContext *sc = st->priv_data; @@ -1060,6 +1085,7 @@ static int64_t mxf_write_cdci_common(AVFormatContext *s, AVStream *st, const UID const MXFCodecUL *color_trc_ul; const MXFCodecUL *color_space_ul; int64_t pos = mxf_write_generic_desc(s, st, key); + uint8_t *side_data; color_primaries_ul = mxf_get_codec_ul_by_id(ff_mxf_color_primaries_uls, st->codecpar->color_primaries); color_trc_ul = mxf_get_codec_ul_by_id(ff_mxf_color_trc_uls, st->codecpar->color_trc); @@ -1228,6 +1254,36 @@ static int64_t mxf_write_cdci_common(AVFormatContext *s, AVStream *st, const UID mxf_write_local_tag(pb, 16, 0x3201); avio_write(pb, *sc->codec_ul, 16); + // Mastering Display metadata + side_data = av_stream_get_side_data(st, AV_PKT_DATA_MASTERING_DISPLAY_METADATA, NULL); + if (side_data) { + const AVMasteringDisplayMetadata *metadata = (const AVMasteringDisplayMetadata*)side_data; + const int chroma_den = 50000; + const int luma_den = 10000; + if (metadata->has_primaries) { + mxf_write_local_tag(pb, 12, 0x8201); + avio_wb16(pb, rescale_mastering(metadata->display_primaries[0][0], chroma_den)); + avio_wb16(pb, rescale_mastering(metadata->display_primaries[0][1], chroma_den)); + avio_wb16(pb, rescale_mastering(metadata->display_primaries[1][0], chroma_den)); + avio_wb16(pb, rescale_mastering(metadata->display_primaries[1][1], chroma_den)); + avio_wb16(pb, rescale_mastering(metadata->display_primaries[2][0], chroma_den)); + avio_wb16(pb, rescale_mastering(metadata->display_primaries[2][1], chroma_den)); + mxf_write_local_tag(pb, 4, 0x8202); + avio_wb16(pb, rescale_mastering(metadata->white_point[0], chroma_den)); + avio_wb16(pb, rescale_mastering(metadata->white_point[1], chroma_den)); + } else { + av_log(NULL, AV_LOG_VERBOSE, "Not writing mastering display primaries. Missing data.\n"); + } + if (metadata->has_luminance) { + mxf_write_local_tag(pb, 4, 0x8203); + avio_wb32(pb, rescale_mastering(metadata->max_luminance, luma_den)); + mxf_write_local_tag(pb, 4, 0x8204); + avio_wb32(pb, rescale_mastering(metadata->min_luminance, luma_den)); + } else { + av_log(NULL, AV_LOG_VERBOSE, "Not writing mastering display luminances. Missing data.\n"); + } + } + if (sc->interlaced && sc->field_dominance) { mxf_write_local_tag(pb, 1, 0x3212); avio_w8(pb, sc->field_dominance);