diff mbox

[FFmpeg-devel] mov: add channel label support

Message ID 20180317022934.24114-1-cidstrom@telltalegames.com
State New
Headers show

Commit Message

Courtland Idstrom March 17, 2018, 2:29 a.m. UTC
Adds the ability to support writing channel labels to mov files if the layout_tag fails, instead of printing a warning and skipping the tag. This fixes channels such as DL/DR, which will now write to LeftTotal/RightTotal instead of omitting the channel tag.
---
 Changelog              |  1 +
 libavformat/mov_chan.c | 20 ++++++++++++++++++++
 libavformat/mov_chan.h |  8 ++++++++
 libavformat/movenc.c   | 38 +++++++++++++++++++++++++++++++-------
 4 files changed, 60 insertions(+), 7 deletions(-)

Comments

Carl Eugen Hoyos March 17, 2018, 1:25 p.m. UTC | #1
2018-03-17 3:29 GMT+01:00, Courtland Idstrom <cidstrom@telltalegames.com>:
> Adds the ability to support writing channel labels to mov files if the
> layout_tag fails, instead of printing a warning and skipping the tag. This

> fixes channels such as DL/DR, which will now write to LeftTotal/RightTotal

Is this correct?

> instead of omitting the channel tag.
> ---
>  Changelog              |  1 +
>  libavformat/mov_chan.c | 20 ++++++++++++++++++++
>  libavformat/mov_chan.h |  8 ++++++++
>  libavformat/movenc.c   | 38 +++++++++++++++++++++++++++++++-------
>  4 files changed, 60 insertions(+), 7 deletions(-)
>
> diff --git a/Changelog b/Changelog
> index 32a93d916a..d9b46b6d78 100644
> --- a/Changelog
> +++ b/Changelog
> @@ -48,6 +48,7 @@ version <next>:
>  - drmeter audio filter
>  - hapqa_extract bitstream filter
>  - movenc option to write track title metadata
> +- mov: write channel labels if channel layout is not found

No Changelog entry needed.

Carl Eugen
Courtland Idstrom March 17, 2018, 7:34 p.m. UTC | #2
>
> > fixes channels such as DL/DR, which will now write to
> LeftTotal/RightTotal
> Is this correct?


To the best of my understanding, this is correct; however, I'm by no means
an expert on this subject, so I'd love to know if I'm wrong here. The
flip-side for reading MOVs is already implemented in ffmpeg (ffprobe will
report LeftTotal, RightTotal mapping to DL/DR, see mov_get_channel_label in
mov_chan.c).

Thanks
-Courtland
diff mbox

Patch

diff --git a/Changelog b/Changelog
index 32a93d916a..d9b46b6d78 100644
--- a/Changelog
+++ b/Changelog
@@ -48,6 +48,7 @@  version <next>:
 - drmeter audio filter
 - hapqa_extract bitstream filter
 - movenc option to write track title metadata
+- mov: write channel labels if channel layout is not found
 
 version 3.4:
 - deflicker video filter
diff --git a/libavformat/mov_chan.c b/libavformat/mov_chan.c
index 324dd5f913..4eb434a97b 100644
--- a/libavformat/mov_chan.c
+++ b/libavformat/mov_chan.c
@@ -478,6 +478,26 @@  uint64_t ff_mov_get_channel_layout(uint32_t tag, uint32_t bitmap)
     return layout_map[i].layout;
 }
 
+uint32_t ff_mov_get_channel_label_tag(uint64_t channel)
+{
+    int i;
+    
+    if(channel == 0)
+        return 0;
+    
+    for(i=0; i<=17; ++i)
+        if((1U << i) & channel)
+            return i+1;
+    
+    if(channel == AV_CH_STEREO_LEFT)
+        return 38; // LeftTotal
+    
+    if(channel == AV_CH_STEREO_RIGHT)
+        return 39; // RightTotal
+
+    return 0;
+}
+
 static uint32_t mov_get_channel_label(uint32_t label)
 {
     if (label == 0)
diff --git a/libavformat/mov_chan.h b/libavformat/mov_chan.h
index ca28345aef..81acb73655 100644
--- a/libavformat/mov_chan.h
+++ b/libavformat/mov_chan.h
@@ -53,6 +53,14 @@  uint32_t ff_mov_get_channel_layout_tag(enum AVCodecID codec_id,
                                        uint64_t channel_layout,
                                        uint32_t *bitmap);
 
+/**
+ * Get the channel label tag for the specified channel.
+ *
+ * @param[in]  channel         channel identifier
+ * @return                     channel label tag
+ */
+uint32_t ff_mov_get_channel_label_tag(uint64_t channel);
+
 /**
  * Read 'chan' tag from the input stream.
  *
diff --git a/libavformat/movenc.c b/libavformat/movenc.c
index ea48c3293e..2c79462e9f 100644
--- a/libavformat/movenc.c
+++ b/libavformat/movenc.c
@@ -742,30 +742,54 @@  static int mov_write_dops_tag(AVIOContext *pb, MOVTrack *track)
     return update_size(pb, pos);
 }
 
+static void mov_write_channel_layout_label_tags(AVFormatContext *s, AVIOContext *pb, uint64_t channel_layout)
+{
+    int i, channels;
+    
+    channels = av_get_channel_layout_nb_channels(channel_layout);
+    
+    for(i=0; i<channels; ++i)
+    {
+        int32_t channel, channel_label_tag;
+        
+        channel = av_channel_layout_extract_channel(channel_layout, i);
+        channel_label_tag = ff_mov_get_channel_label_tag(channel);
+        
+        av_log(s, AV_LOG_WARNING, "label[%d] = %d\n", i, channel_label_tag);
+        
+        avio_wb32(pb, channel_label_tag);  // mChannelLabel
+        avio_wb32(pb, 0);                  // mChannelFlags
+        avio_wb32(pb, 0);                  // mCoordinates[0]
+        avio_wb32(pb, 0);                  // mCoordinates[1]
+        avio_wb32(pb, 0);                  // mCoordinates[2]
+    }
+}
+
 static int mov_write_chan_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
 {
-    uint32_t layout_tag, bitmap;
+    uint32_t layout_tag, bitmap, num_channel_desc;
     int64_t pos = avio_tell(pb);
 
     layout_tag = ff_mov_get_channel_layout_tag(track->par->codec_id,
                                                track->par->channel_layout,
                                                &bitmap);
-    if (!layout_tag) {
-        av_log(s, AV_LOG_WARNING, "not writing 'chan' tag due to "
-               "lack of channel information\n");
-        return 0;
-    }
 
     if (track->multichannel_as_mono)
         return 0;
 
+    num_channel_desc = layout_tag == 0 ? av_get_channel_layout_nb_channels(track->par->channel_layout) : 0;
+
     avio_wb32(pb, 0);           // Size
     ffio_wfourcc(pb, "chan");   // Type
     avio_w8(pb, 0);             // Version
     avio_wb24(pb, 0);           // Flags
     avio_wb32(pb, layout_tag);  // mChannelLayoutTag
     avio_wb32(pb, bitmap);      // mChannelBitmap
-    avio_wb32(pb, 0);           // mNumberChannelDescriptions
+    avio_wb32(pb, num_channel_desc); // mNumberChannelDescriptions
+    
+    if(!layout_tag) {
+        mov_write_channel_layout_label_tags(s, pb, track->par->channel_layout);
+    }
 
     return update_size(pb, pos);
 }