[FFmpeg-devel] [PATCH]Reorder channels for some mov channel layouts
Carl Eugen Hoyos
cehoyos at ag.or.at
Wed Jun 22 19:21:03 CEST 2011
On Friday 17 June 2011 06:46:41 pm Michael Niedermayer wrote:
> On Mon, Jun 13, 2011 at 10:01:51PM +0200, Carl Eugen Hoyos wrote:
> > Attached patch fixes ticket 98.
> >
> > Please comment, Carl Eugen
> >
> > libavcodec/avcodec.h | 7 +++
> > libavcodec/pcm.c | 99
> > +++++++++++++++++++++++++++++++++++++++++++++++++++ libavformat/isom.c
> > | 3 -
>
> missing entry in the AVOption array
Updated patch attached.
Please comment, Carl Eugen
-------------- next part --------------
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 90c389b..dd7e249 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -2903,6 +2903,13 @@ typedef struct AVCodecContext {
int64_t pts_correction_last_dts; /// DTS of the last frame
+ /**
+ * mov channel layout tag as described in the CAF specification.
+ * - decoding: Set by user.
+ * - encoding: unused
+ */
+ uint32_t mov_channel_layout;
+
} AVCodecContext;
/**
diff --git a/libavcodec/options.c b/libavcodec/options.c
index b6ad5d8..341d5dc 100644
--- a/libavcodec/options.c
+++ b/libavcodec/options.c
@@ -418,6 +418,7 @@ static const AVOption options[]={
{"mbtree", "use macroblock tree ratecontrol (x264 only)", 0, FF_OPT_TYPE_CONST, {.dbl = CODEC_FLAG2_MBTREE }, INT_MIN, INT_MAX, V|E, "flags2"},
{"bits_per_raw_sample", NULL, OFFSET(bits_per_raw_sample), FF_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX},
{"channel_layout", NULL, OFFSET(channel_layout), FF_OPT_TYPE_INT64, {.dbl = DEFAULT }, 0, INT64_MAX, A|E|D, "channel_layout"},
+{"mov_channel_layout", "mov channel layout as used in mov/aif/caf files", OFFSET(mov_channel_layout), FF_OPT_TYPE_INT, {.dbl = DEFAULT }, 0, INT_MAX, A|D},
{"request_channel_layout", NULL, OFFSET(request_channel_layout), FF_OPT_TYPE_INT64, {.dbl = DEFAULT }, 0, INT64_MAX, A|D, "request_channel_layout"},
{"rc_max_vbv_use", NULL, OFFSET(rc_max_available_vbv_use), FF_OPT_TYPE_FLOAT, {.dbl = 1.0/3 }, 0.0, FLT_MAX, V|E},
{"rc_min_vbv_use", NULL, OFFSET(rc_min_vbv_overflow_use), FF_OPT_TYPE_FLOAT, {.dbl = 3 }, 0.0, FLT_MAX, V|E},
diff --git a/libavcodec/pcm.c b/libavcodec/pcm.c
index 111ce61..5329c56 100644
--- a/libavcodec/pcm.c
+++ b/libavcodec/pcm.c
@@ -204,13 +204,63 @@ static int pcm_encode_frame(AVCodecContext *avctx,
return dst - frame;
}
+typedef struct Channel_maps {
+ uint32_t layout_tag;
+ int64_t channel_layout;
+ uint8_t channel_map[8];
+} Channel_maps;
+
+static const Channel_maps channel_maps[] = {
+ /* kCAFChannelLayoutTag_Pentagonal */
+ { (109 << 16) | 5, AV_CH_LAYOUT_5POINT0_BACK, { 0, 1, 4, 2, 3 } },
+ /* kCAFChannelLayoutTag_Hexagonal */
+ { (110 << 16) | 6, AV_CH_LAYOUT_5POINT0_BACK|AV_CH_BACK_CENTER, { 0, 1, 4, 2, 3, 5 } },
+ /* kCAFChannelLayoutTag_MPEG_3_0_B */
+ { (114 << 16) | 3, AV_CH_LAYOUT_SURROUND, { 1, 2, 0 } },
+ /* kCAFChannelLayoutTag_MPEG_4_0_B */
+ { (116 << 16) | 4, AV_CH_LAYOUT_4POINT0, { 1, 2, 0, 3 } },
+ /* kCAFChannelLayoutTag_MPEG_5_0_B */
+ { (118 << 16) | 5, AV_CH_LAYOUT_5POINT0_BACK, { 0, 1, 4, 2, 3 } },
+ /* kCAFChannelLayoutTag_MPEG_5_0_C */
+ { (119 << 16) | 5, AV_CH_LAYOUT_5POINT0_BACK, { 0, 2, 1, 3, 4 } },
+ /* kCAFChannelLayoutTag_MPEG_5_0_D */
+ { (120 << 16) | 5, AV_CH_LAYOUT_5POINT0_BACK, { 1, 2, 0, 3, 4 } },
+ /* kCAFChannelLayoutTag_MPEG_5_1_B */
+ { (122 << 16) | 6, AV_CH_LAYOUT_5POINT1_BACK, { 0, 1, 4, 5, 2, 3 } },
+ /* kCAFChannelLayoutTag_MPEG_5_1_C */
+ { (123 << 16) | 6, AV_CH_LAYOUT_5POINT1_BACK, { 0, 2, 1, 5, 3, 4 } },
+ /* kCAFChannelLayoutTag_MPEG_5_1_D */
+ { (124 << 16) | 6, AV_CH_LAYOUT_5POINT1_BACK, { 1, 2, 0, 5, 3, 4 } },
+ /* kCAFChannelLayoutTag_MPEG_7_1_B */
+ { (127 << 16) | 8, AV_CH_LAYOUT_7POINT1_WIDE, { 3, 4, 0, 7, 5, 6, 1, 2 } },
+ /* kCAFChannelLayoutTag_Emagic_Default_7_1 */
+ { (129 << 16) | 8, AV_CH_LAYOUT_7POINT1_WIDE, { 0, 1, 4, 5, 2, 3, 6, 7 } },
+ /* kCAFChannelLayoutTag_AudioUnit_6_0 */
+ { (139 << 16) | 6, AV_CH_LAYOUT_5POINT0_BACK|AV_CH_BACK_CENTER, { 0, 1, 4, 2, 3, 5 } },
+ /* kCAFChannelLayoutTag_AudioUnit_7_0 */
+ { (140 << 16) | 7, AV_CH_LAYOUT_7POINT0, { 0, 1, 4, 5, 6, 2, 3 } },
+ /* kCAFChannelLayoutTag_AAC_6_0 */
+ { (141 << 16) | 6, AV_CH_LAYOUT_5POINT0_BACK|AV_CH_BACK_CENTER, { 1, 2, 0, 3, 4, 5 } },
+ /* kCAFChannelLayoutTag_AAC_6_1 */
+ { (142 << 16) | 7, AV_CH_LAYOUT_5POINT1_BACK|AV_CH_BACK_CENTER, { 1, 2, 0, 6, 3, 4, 5 } },
+ /* kCAFChannelLayoutTag_AAC_7_0 */
+ { (143 << 16) | 7, AV_CH_LAYOUT_7POINT0, { 1, 2, 0, 5, 6, 3, 4 } },
+ /* kCAFChannelLayoutTag_AAC_Octagonal */
+ { (144 << 16) | 8, AV_CH_LAYOUT_7POINT0|AV_CH_BACK_CENTER, { 1, 2, 0, 5, 6, 7, 3, 4 } },
+ { 0 },
+};
+
typedef struct PCMDecode {
short table[256];
+ const uint8_t *channel_map;
+ uint8_t *reorder_buf;
+ unsigned int buf_size;
} PCMDecode;
static av_cold int pcm_decode_init(AVCodecContext * avctx)
{
PCMDecode *s = avctx->priv_data;
+ const Channel_maps *channel_map = channel_maps;
int i;
switch(avctx->codec->id) {
@@ -231,6 +281,19 @@ static av_cold int pcm_decode_init(AVCodecContext * avctx)
if (avctx->sample_fmt == AV_SAMPLE_FMT_S32)
avctx->bits_per_raw_sample = av_get_bits_per_sample(avctx->codec->id);
+ if(avctx->mov_channel_layout) {
+ while(channel_map->layout_tag) {
+ if(channel_map->layout_tag == avctx->mov_channel_layout &&
+ (channel_map->layout_tag & 0xF) == avctx->channels) {
+ s->channel_map = channel_map->channel_map;
+ avctx->channel_layout = channel_map->channel_layout;
+ break;
+ }
+ channel_map++;
+ }
+ if (!avctx->channel_layout)
+ av_log_ask_for_sample(s, "Unknown channel layout.\n");
+ }
return 0;
}
@@ -468,9 +531,47 @@ static int pcm_decode_frame(AVCodecContext *avctx,
return -1;
}
*data_size = (uint8_t *)samples - (uint8_t *)data;
+
+ if (s->channel_map) {
+ s->reorder_buf = av_fast_realloc(s->reorder_buf, &s->buf_size, *data_size);
+ memcpy(s->reorder_buf, data, *data_size);
+ for (i = 0; i < buf_size/sample_size / avctx->channels; i++)
+ for (c = 0; c < avctx->channels; c++)
+ switch (avctx->sample_fmt) {
+ case AV_SAMPLE_FMT_U8:
+ ((uint8_t *)data)[i * avctx->channels + c] =
+ s->reorder_buf[i * avctx->channels + s->channel_map[c]];
+ break;
+ case AV_SAMPLE_FMT_S16:
+ ((int16_t *)data)[i * avctx->channels + c] =
+ ((int16_t *)s->reorder_buf)[i * avctx->channels + s->channel_map[c]];
+ break;
+ case AV_SAMPLE_FMT_S32:
+ ((int32_t *)data)[i * avctx->channels + c] =
+ ((int32_t *)s->reorder_buf)[i * avctx->channels + s->channel_map[c]];
+ break;
+ case AV_SAMPLE_FMT_FLT:
+ ((float *)data)[i * avctx->channels + c] =
+ ((float *)s->reorder_buf)[i * avctx->channels + s->channel_map[c]];
+ break;
+ case AV_SAMPLE_FMT_DBL:
+ ((double *)data)[i * avctx->channels + c] =
+ ((double *)s->reorder_buf)[i * avctx->channels + s->channel_map[c]];
+ break;
+ }
+ }
+
return src - buf;
}
+static av_cold int pcm_decode_close(AVCodecContext *avctx)
+{
+ PCMDecode *s = avctx->priv_data;
+ av_freep(&s->reorder_buf);
+
+ return 0;
+}
+
#if CONFIG_ENCODERS
#define PCM_ENCODER(id_,sample_fmt_,name_,long_name_) \
AVCodec ff_ ## name_ ## _encoder = { \
@@ -496,6 +597,7 @@ AVCodec ff_ ## name_ ## _decoder = { \
.priv_data_size = sizeof(PCMDecode), \
.init = pcm_decode_init, \
.decode = pcm_decode_frame, \
+ .close = pcm_decode_close, \
.sample_fmts = (const enum AVSampleFormat[]){sample_fmt_,AV_SAMPLE_FMT_NONE}, \
.long_name = NULL_IF_CONFIG_SMALL(long_name_), \
}
diff --git a/libavcodec/version.h b/libavcodec/version.h
index 100c06d..e4888d9 100644
--- a/libavcodec/version.h
+++ b/libavcodec/version.h
@@ -21,7 +21,7 @@
#define AVCODEC_VERSION_H
#define LIBAVCODEC_VERSION_MAJOR 53
-#define LIBAVCODEC_VERSION_MINOR 7
+#define LIBAVCODEC_VERSION_MINOR 8
#define LIBAVCODEC_VERSION_MICRO 0
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
diff --git a/libavformat/isom.c b/libavformat/isom.c
index 09ee23b..12cee67 100644
--- a/libavformat/isom.c
+++ b/libavformat/isom.c
@@ -476,6 +476,7 @@ void ff_mov_read_chan(AVFormatContext *s, int64_t size, AVCodecContext *codec)
avio_skip(pb, size);
return;
}
+ codec->mov_channel_layout = layout_tag;
while (layouts->channel_layout) {
if (layout_tag == layouts->layout_tag) {
codec->channel_layout = layouts->channel_layout;
@@ -483,8 +484,6 @@ void ff_mov_read_chan(AVFormatContext *s, int64_t size, AVCodecContext *codec)
}
layouts++;
}
- if (!codec->channel_layout)
- av_log(s, AV_LOG_WARNING, "Unknown container channel layout.\n");
avio_skip(pb, size);
}
More information about the ffmpeg-devel
mailing list