[FFmpeg-devel] [PATCH]caf channel layout

Carl Eugen Hoyos cehoyos at ag.or.at
Wed Apr 20 14:46:34 CEST 2011


Hi!

Attached patch implements two of three possible caf channel layout types.

Please comment, Carl Eugen
-------------- next part --------------
diff --git a/libavformat/caf.c b/libavformat/caf.c
index 96fb847..e546258 100644
--- a/libavformat/caf.c
+++ b/libavformat/caf.c
@@ -56,3 +56,25 @@ const AVCodecTag ff_codec_caf_tags[] = {
   /*{ MPEG4TwinVQ               MKBETAG('t','w','v','q') },*/
     { CODEC_ID_NONE,            0 },
 };
+
+const CafChannelLayout ff_caf_channel_layout[] = {
+    { AV_CH_LAYOUT_MONO,                           (100<<16) | 1}, //< kCAFChannelLayoutTag_Mono
+    { AV_CH_LAYOUT_STEREO,                         (101<<16) | 2}, //< kCAFChannelLayoutTag_Stereo
+    { AV_CH_LAYOUT_STEREO,                         (102<<16) | 2}, //< kCAFChannelLayoutTag_StereoHeadphones
+    { AV_CH_LAYOUT_2_1,                            (131<<16) | 3}, //< kCAFChannelLayoutTag_ITU_2_1
+    { AV_CH_LAYOUT_2_2,                            (132<<16) | 4}, //< kCAFChannelLayoutTag_ITU_2_2
+    { AV_CH_LAYOUT_QUAD,                           (108<<16) | 4}, //< kCAFChannelLayoutTag_Quadraphonic
+    { AV_CH_LAYOUT_SURROUND,                       (113<<16) | 3}, //< kCAFChannelLayoutTag_MPEG_3_0_A
+    { AV_CH_LAYOUT_4POINT0,                        (115<<16) | 4}, //< kCAFChannelLayoutTag_MPEG_4_0_A
+    { AV_CH_LAYOUT_5POINT0,                        (117<<16) | 5}, //< kCAFChannelLayoutTag_MPEG_5_0_A
+    { AV_CH_LAYOUT_5POINT1,                        (121<<16) | 6}, //< kCAFChannelLayoutTag_MPEG_5_1_A
+    { AV_CH_LAYOUT_7POINT1,                        (128<<16) | 8}, //< kCAFChannelLayoutTag_MPEG_7_1_C
+    { AV_CH_LAYOUT_7POINT1_WIDE,                   (126<<16) | 8}, //< kCAFChannelLayoutTag_MPEG_7_1_A
+    { (AV_CH_LAYOUT_STEREO|AV_CH_LOW_FREQUENCY),   (133<<16) | 3}, //< kCAFChannelLayoutTag_DVD_4
+    { (AV_CH_LAYOUT_2_1|AV_CH_LOW_FREQUENCY),      (134<<16) | 4}, //< kCAFChannelLayoutTag_DVD_5
+    { (AV_CH_LAYOUT_2_2|AV_CH_LOW_FREQUENCY),      (135<<16) | 4}, //< kCAFChannelLayoutTag_DVD_6
+    { (AV_CH_LAYOUT_SURROUND|AV_CH_LOW_FREQUENCY), (136<<16) | 4}, //< kCAFChannelLayoutTag_DVD_10
+    { (AV_CH_LAYOUT_4POINT0|AV_CH_LOW_FREQUENCY),  (137<<16) | 5}, //< kCAFChannelLayoutTag_DVD_11
+    { 0, 0},
+};
+
diff --git a/libavformat/caf.h b/libavformat/caf.h
index 9c25f2c..e41ae06 100644
--- a/libavformat/caf.h
+++ b/libavformat/caf.h
@@ -31,4 +31,11 @@
 
 extern const AVCodecTag ff_codec_caf_tags[];
 
+typedef struct CafChannelLayout {
+    int64_t  channel_layout;
+    uint32_t layout_tag;
+} CafChannelLayout;
+
+extern const CafChannelLayout ff_caf_channel_layout[];
+
 #endif /* AVFORMAT_CAF_H */
diff --git a/libavformat/cafdec.c b/libavformat/cafdec.c
index 16c4674..089d44b 100644
--- a/libavformat/cafdec.c
+++ b/libavformat/cafdec.c
@@ -191,6 +191,35 @@ static void read_info_chunk(AVFormatContext *s, int64_t size)
     }
 }
 
+/** Read channel chunk */
+static void read_chan_chunk(AVIOContext *pb, int64_t size,
+                            AVCodecContext *codec)
+{
+    uint32_t layout_tag;
+    const CafChannelLayout *caf_layout = ff_caf_channel_layout;
+    if (size != 12) {
+        // Channel descriptions not implemented
+        avio_skip(pb, size);
+        return;
+    }
+    layout_tag = avio_rb32(pb);
+    if (layout_tag == 0x10000) { //< kCAFChannelLayoutTag_UseChannelBitmap
+        codec->channel_layout = avio_rb32(pb);
+        avio_skip(pb, 4);
+        return;
+    }
+    while (caf_layout->channel_layout) {
+        if (layout_tag == caf_layout->layout_tag) {
+            codec->channel_layout = caf_layout->channel_layout;
+            break;
+        }
+        caf_layout++;
+    }
+    if (!codec->channel_layout)
+        av_log_ask_for_sample(codec, "Unknown channel layout.");
+    avio_skip(pb, 8);
+}
+
 static int read_header(AVFormatContext *s,
                        AVFormatParameters *ap)
 {
@@ -257,5 +286,11 @@ static int read_header(AVFormatContext *s,
             read_info_chunk(s, size);
             break;
 
+        case MKBETAG('c','h','a','n'):
+            if (size < 12)
+                return AVERROR_INVALIDDATA;
+            read_chan_chunk(pb, size, st->codec);
+            break;
+
         default:
 #define _(x) ((x) >= ' ' ? (x) : ' ')


More information about the ffmpeg-devel mailing list