[FFmpeg-devel] lavf/matroskaenc.c: use metadata key/value to set mastering metadata

Submitted by Neil Birkbeck on Nov. 4, 2016, 3:10 p.m.

Details

Message ID CAB8cQe7W1V0PGjxbr9OvF5CoZ7=3odZVwsxd+fOQ4+TfFjrE0w@mail.gmail.com
State New
Headers show

Commit Message

Neil Birkbeck Nov. 4, 2016, 3:10 p.m.
On Wed, Jun 8, 2016 at 11:27 PM, Dave Rice <dave@dericed.com> wrote:

>
> > On Jun 8, 2016, at 11:03 PM, Neil Birkbeck <neil.birkbeck@gmail.com>
> wrote:
> >
> > The most recent patch should still apply cleanly (unless we have a
> > better way to set these elements). Thanks
>
> There are specific mastering metadata elements as recently defined in the
> Matroska specification [1]. It would be better to use these defined
> elements from the specification rather than somehow fit this data into tags.
> Dave Rice
>
> [1] https://matroska.org/technical/specs/index.html#MasteringMetadata


Yes, the new elements are read and written, and are propagated within
ffmpeg in side data. This patch is to address how we can manually specify
those values when creating a new file from an input that doesn't have the
metadata already. The current patch doesn't write them to tags in the
output file, but uses the "metadata" command line. I kept this like
stereo_mode, but maybe we should instead use specific muxer option to do
this? Or perhaps there is another generic way to instantiate side data from
command line upstream from the muxer that I am missing.


>
>
> > On Tue, Apr 19, 2016 at 8:12 AM, Neil Birkbeck <neil.birkbeck@gmail.com>
> wrote:
> >> Updated patch attached.
> >>
> >> On Sat, Apr 16, 2016 at 7:08 PM, Michael Niedermayer
> >> <michael@niedermayer.cc> wrote:
> >>> On Sun, Apr 03, 2016 at 03:38:33PM -0700, Neil Birkbeck wrote:
> >>>> 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.
> >>>
> >>>> matroskaenc.c |   51 ++++++++++++++++++++++++++++++
> +++++++++++++++++----
> >>>> 1 file changed, 47 insertions(+), 4 deletions(-)
> >>>> d92564f3ec6cf08430a79b64f4d1ec304637afe1
> 0001-lavf-matroskaenc.c-use-metadata-key-value-to-set-mas.patch
> >>>> From b30d80f6ba4b09811039f64af3e7f709d86df5fe Mon Sep 17 00:00:00
> 2001
> >>>> From: Neil Birkbeck <neil.birkbeck@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.birkbeck@gmail.com>
> >>>
> >>> this does not apply cleanly anymore after codecpar
> >>>
> >>> Applying: lavf/matroskaenc.c: use metadata key/value to set mastering
> metadata
> >>> Using index info to reconstruct a base tree...
> >>> Falling back to patching base and 3-way merge...
> >>> Auto-merging libavformat/matroskaenc.c
> >>> CONFLICT (content): Merge conflict in libavformat/matroskaenc.c
> >>> Failed to merge in the changes.
> >>> Patch failed at 0001 lavf/matroskaenc.c: use metadata key/value to set
> mastering metadata
> >>> When you have resolved this problem run "git am --resolved".
> >>> If you would prefer to skip this patch, instead run "git am --skip".
> >>> To restore the original branch and stop patching run "git am --abort".
> >>>
> >>>
> >>> [...]
> >>>
> >>> --
> >>> Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC7
> 87040B0FAB
> >>>
> >>> Democracy is the form of government in which you can choose your
> dictator
> >>>
> >>> _______________________________________________
> >>> ffmpeg-devel mailing list
> >>> ffmpeg-devel@ffmpeg.org
> >>> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> >>>
> > _______________________________________________
> > ffmpeg-devel mailing list
> > ffmpeg-devel@ffmpeg.org
> > http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>

Patch hide | download patch | download mbox

From e83d6ca87c7da2d6a9ff09dcec339cadc054610f Mon Sep 17 00:00:00 2001
From: Neil Birkbeck <neil.birkbeck@gmail.com>
Date: Thu, 3 Nov 2016 17:13:03 -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.birkbeck@gmail.com>
---
 libavformat/matroskaenc.c | 49 ++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 46 insertions(+), 3 deletions(-)

diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c
index 2cfeee9..4287171 100644
--- a/libavformat/matroskaenc.c
+++ b/libavformat/matroskaenc.c
@@ -804,17 +804,61 @@  static int mkv_write_codecprivate(AVFormatContext *s, AVIOContext *pb,
 }
 
 static int mkv_write_video_color(AVIOContext *pb, AVCodecParameters *par, AVStream *st) {
+    AVDictionaryEntry *tag;
     AVIOContext *dyn_cp;
     uint8_t *colorinfo_ptr;
     int side_data_size = 0;
     int ret, colorinfo_size;
     const uint8_t *side_data = av_stream_get_side_data(
         st, AV_PKT_DATA_MASTERING_DISPLAY_METADATA, &side_data_size);
+    AVMasteringDisplayMetadata *metadata =
+        (side_data_size == sizeof(AVMasteringDisplayMetadata)) ?
+        (AVMasteringDisplayMetadata*)side_data : NULL;
 
     ret = avio_open_dyn_buf(&dyn_cp);
     if (ret < 0)
         return ret;
 
+    // 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 (par->color_trc != AVCOL_TRC_UNSPECIFIED &&
         par->color_trc < AVCOL_TRC_NB) {
         put_ebml_uint(dyn_cp, MATROSKA_ID_VIDEOCOLORTRANSFERCHARACTERISTICS,
@@ -840,11 +884,9 @@  static int mkv_write_video_color(AVIOContext *pb, AVCodecParameters *par, AVStre
         put_ebml_uint(dyn_cp, MATROSKA_ID_VIDEOCOLORCHROMASITINGHORZ, (xpos >> 7) + 1);
         put_ebml_uint(dyn_cp, MATROSKA_ID_VIDEOCOLORCHROMASITINGVERT, (ypos >> 7) + 1);
     }
-    if (side_data_size == sizeof(AVMasteringDisplayMetadata)) {
+    if (metadata) {
         ebml_master meta_element = start_ebml_master(
             dyn_cp, MATROSKA_ID_VIDEOCOLORMASTERINGMETA, 0);
-        const AVMasteringDisplayMetadata *metadata =
-            (const AVMasteringDisplayMetadata*)side_data;
         if (metadata->has_primaries) {
             put_ebml_float(dyn_cp, MATROSKA_ID_VIDEOCOLOR_RX,
                            av_q2d(metadata->display_primaries[0][0]));
@@ -1425,6 +1467,7 @@  static int mkv_check_tag_name(const char *name, unsigned int elementid)
 {
     return av_strcasecmp(name, "title") &&
            av_strcasecmp(name, "stereo_mode") &&
+           av_strcasecmp(name, "master_display") &&
            av_strcasecmp(name, "creation_time") &&
            av_strcasecmp(name, "encoding_tool") &&
            av_strcasecmp(name, "duration") &&
-- 
2.8.0.rc3.226.g39d4020