Use "master_display" key/value pair to specify mastering metadata in a
similar formatting as accepted by libx265 (unless there is some other
generic way to add side data to a stream from command line).
Currently, the packet side data propagates from an input file to
output file if it is transmuxed (mkv -> mkv). Perhaps we want to also
use this same metadata key in matroskadec to also allow for the
metadata to propagate during transcoding.
From b30d80f6ba4b09811039f64af3e7f709d86df5fe Mon Sep 17 00:00:00 2001
From: Neil Birkbeck <neil.birkb...@gmail.com>
Date: Fri, 1 Apr 2016 17:02:42 -0700
Subject: [PATCH] lavf/matroskaenc.c: use metadata key/value to set mastering
 metadata

Add key/value metadata interface to allow command line setting of AVMasteringDisplayMetadata. The formatting is the same as the option in libx265.

Signed-off-by: Neil Birkbeck <neil.birkb...@gmail.com>
---
 libavformat/matroskaenc.c | 51 +++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 47 insertions(+), 4 deletions(-)

diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c
index 0546686..30ff714 100644
--- a/libavformat/matroskaenc.c
+++ b/libavformat/matroskaenc.c
@@ -732,10 +732,54 @@ static int mkv_write_codecprivate(AVFormatContext *s, AVIOContext *pb,
 }
 
 static int mkv_write_video_color(AVIOContext *pb, AVCodecContext *codec, AVStream *st) {
+    AVDictionaryEntry *tag;
     int side_data_size = 0;
-    const uint8_t *side_data = av_stream_get_side_data(
+    uint8_t *side_data = av_stream_get_side_data(
         st, AV_PKT_DATA_MASTERING_DISPLAY_METADATA, &side_data_size);
     ebml_master colorinfo = start_ebml_master(pb, MATROSKA_ID_VIDEOCOLOR, 0);
+    AVMasteringDisplayMetadata *metadata =
+        (side_data_size == sizeof(AVMasteringDisplayMetadata)) ?
+        (AVMasteringDisplayMetadata*)side_data : NULL;
+
+    // If key-value pair metadata is specified, override the packet side data
+    // Accept a format similar to the command line argument in x265:
+    //    G(x,y)B(x,y)R(x,y)WP(x,y),L(max,min)
+    if (tag = av_dict_get(st->metadata, "master_display", NULL, 0)) {
+        int primaries[4][2];
+        int luma[2];
+        int num_read = sscanf(tag->value,
+                              "G(%d,%d)B(%d,%d)R(%d,%d)WP(%d,%d)L(%d,%d)",
+                              primaries[1], primaries[1] + 1,
+                              primaries[2], primaries[2] + 1,
+                              primaries[0], primaries[0] + 1,
+                              primaries[3], primaries[3] + 1,
+                              luma + 1, luma + 0);
+        if (num_read >= 8) {
+            const float chroma_denom = 50000.f;
+            const float luma_denom = 10000.f;
+            int i, j;
+            if (!metadata) {
+                metadata = (AVMasteringDisplayMetadata*) av_stream_new_side_data(
+                    st, AV_PKT_DATA_MASTERING_DISPLAY_METADATA,
+                    sizeof(AVMasteringDisplayMetadata));
+                memset(metadata, 0, sizeof(AVMasteringDisplayMetadata));
+            }
+            for (i = 0; i < 3; ++i) {
+                for (j = 0; j < 2; ++j) {
+                    metadata->display_primaries[i][j] =
+                        av_make_q(primaries[i][j], chroma_denom);
+                }
+            }
+            metadata->white_point[0] = av_make_q(primaries[3][0], chroma_denom);
+            metadata->white_point[1] = av_make_q(primaries[3][1], chroma_denom);
+            metadata->has_primaries = 1;
+            if (num_read == 10) {
+                metadata->min_luminance = av_make_q(luma[0], luma_denom);
+                metadata->max_luminance = av_make_q(luma[1], luma_denom);
+                metadata->has_luminance = 1;
+            }
+        }
+    }
 
     if (codec->color_trc != AVCOL_TRC_UNSPECIFIED &&
         codec->color_trc < AVCOL_TRC_NB) {
@@ -754,11 +798,9 @@ static int mkv_write_video_color(AVIOContext *pb, AVCodecContext *codec, AVStrea
         codec->color_range < AVCOL_RANGE_NB) {
         put_ebml_uint(pb, MATROSKA_ID_VIDEOCOLORRANGE, codec->color_range);
     }
-    if (side_data_size == sizeof(AVMasteringDisplayMetadata)) {
+    if (metadata) {
         ebml_master meta_element = start_ebml_master(
             pb, MATROSKA_ID_VIDEOCOLORMASTERINGMETA, 0);
-        const AVMasteringDisplayMetadata *metadata =
-            (const AVMasteringDisplayMetadata*)side_data;
         if (metadata->has_primaries) {
             put_ebml_float(pb, MATROSKA_ID_VIDEOCOLOR_RX,
                            av_q2d(metadata->display_primaries[0][0]));
@@ -1278,6 +1320,7 @@ static int mkv_write_tag(AVFormatContext *s, AVDictionary *m, unsigned int eleme
             av_strcasecmp(t->key, "stereo_mode") &&
             av_strcasecmp(t->key, "creation_time") &&
             av_strcasecmp(t->key, "encoding_tool") &&
+            av_strcasecmp(t->key, "master_display") &&
             (elementid != MATROSKA_ID_TAGTARGETS_TRACKUID ||
              av_strcasecmp(t->key, "language"))) {
             ret = mkv_write_simpletag(s->pb, t);
-- 
2.8.0.rc3.226.g39d4020

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

Reply via email to