[FFmpeg-devel] [PATCH]caf channel layout, v2
Carl Eugen Hoyos
cehoyos at ag.or.at
Thu Apr 21 12:36:32 CEST 2011
Hi!
Attached patch implements two of three possible caf channel layout types.
Apple decided that the same layout can be used in aif files now.
Please comment, Carl Eugen
-------------- next part --------------
diff --git a/libavformat/Makefile b/libavformat/Makefile
index 4587172..f83642f 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -23,7 +23,7 @@ OBJS-$(CONFIG_AC3_DEMUXER) += ac3dec.o rawdec.o
OBJS-$(CONFIG_AC3_MUXER) += rawenc.o
OBJS-$(CONFIG_ADTS_MUXER) += adtsenc.o
OBJS-$(CONFIG_AEA_DEMUXER) += aea.o pcm.o
-OBJS-$(CONFIG_AIFF_DEMUXER) += aiffdec.o riff.o pcm.o
+OBJS-$(CONFIG_AIFF_DEMUXER) += aiffdec.o riff.o pcm.o caf.o
OBJS-$(CONFIG_AIFF_MUXER) += aiffenc.o riff.o
OBJS-$(CONFIG_AMR_DEMUXER) += amr.o
OBJS-$(CONFIG_AMR_MUXER) += amr.o
diff --git a/libavformat/aiffdec.c b/libavformat/aiffdec.c
index 25a93f5..a3aecee 100644
--- a/libavformat/aiffdec.c
+++ b/libavformat/aiffdec.c
@@ -23,6 +23,7 @@
#include "avformat.h"
#include "pcm.h"
#include "aiff.h"
+#include "caf.h"
#define AIFF 0
#define AIFF_C_VERSION1 0xA2805140
@@ -253,6 +254,11 @@ static int aiff_read_header(AVFormatContext *s,
st->codec->extradata_size = size;
avio_read(pb, st->codec->extradata, size);
break;
+ case MKTAG('C','H','A','N'):
+ if (size < 12)
+ return AVERROR_INVALIDDATA;
+ ff_read_chan_chunk(s, size, st->codec);
+ break;
default: /* Jump */
if (size & 1) /* Always even aligned */
size++;
diff --git a/libavformat/caf.c b/libavformat/caf.c
index 96fb847..bca0d40 100644
--- a/libavformat/caf.c
+++ b/libavformat/caf.c
@@ -56,3 +56,62 @@ const AVCodecTag ff_codec_caf_tags[] = {
/*{ MPEG4TwinVQ MKBETAG('t','w','v','q') },*/
{ CODEC_ID_NONE, 0 },
};
+
+typedef struct CafChannelLayout {
+ int64_t channel_layout;
+ uint32_t layout_tag;
+} CafChannelLayout;
+
+static const CafChannelLayout 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_BACK, (117<<16) | 5}, //< kCAFChannelLayoutTag_MPEG_5_0_A
+ { AV_CH_LAYOUT_5POINT0, (117<<16) | 5}, //< kCAFChannelLayoutTag_MPEG_5_0_A
+ { AV_CH_LAYOUT_5POINT1_BACK, (121<<16) | 6}, //< kCAFChannelLayoutTag_MPEG_5_1_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},
+};
+
+/** Read channel chunk */
+void ff_read_chan_chunk(AVFormatContext *s, int64_t size, AVCodecContext *codec)
+{
+ uint32_t layout_tag;
+ AVIOContext *pb = s->pb;
+ const CafChannelLayout *caf_layout = caf_channel_layout;
+ if (size != 12) {
+ // Channel descriptions not implemented
+ av_log_ask_for_sample(s, "Unimplemented channel layout.");
+ 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(s, AV_LOG_WARNING, "Unknown channel layout.");
+ avio_skip(pb, 8);
+}
+
diff --git a/libavformat/caf.h b/libavformat/caf.h
index 9c25f2c..181cfaf 100644
--- a/libavformat/caf.h
+++ b/libavformat/caf.h
@@ -27,8 +27,11 @@
#ifndef AVFORMAT_CAF_H
#define AVFORMAT_CAF_H
+#include "avformat.h"
#include "internal.h"
extern const AVCodecTag ff_codec_caf_tags[];
+void ff_read_chan_chunk(AVFormatContext *s, int64_t size, AVCodecContext *codec);
+
#endif /* AVFORMAT_CAF_H */
diff --git a/libavformat/cafdec.c b/libavformat/cafdec.c
index 16c4674..a10c42b 100644
--- a/libavformat/cafdec.c
+++ b/libavformat/cafdec.c
@@ -257,5 +257,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;
+ ff_read_chan_chunk(s, size, st->codec);
+ break;
+
default:
#define _(x) ((x) >= ' ' ? (x) : ' ')
More information about the ffmpeg-devel
mailing list