@@ -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
@@ -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)
@@ -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.
*
@@ -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);
}