[FFmpeg-devel] [PATCH]Reorder channels for some mov channel layouts
Carl Eugen Hoyos
cehoyos at ag.or.at
Mon Jun 13 22:01:51 CEST 2011
Hi!
Attached patch fixes ticket 98.
Please comment, Carl Eugen
-------------- next part --------------
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index ef539a2..e651bd9 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -2899,6 +2899,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
+ */
+ int32_t mov_channel_layout;
+
} AVCodecContext;
/**
diff --git a/libavcodec/pcm.c b/libavcodec/pcm.c
index 111ce61..9835582 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,16 @@ 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++;
+ }
return 0;
}
@@ -468,9 +528,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 +594,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/libavformat/isom.c b/libavformat/isom.c
index 45ccdd2..8ed15ea 100644
--- a/libavformat/isom.c
+++ b/libavformat/isom.c
@@ -471,6 +471,7 @@ void ff_mov_read_chan(AVFormatContext *s, int64_t size, AVCodecContext *codec)
avio_skip(pb, 4);
return;
}
+ codec->mov_channel_layout = layout_tag;
while (layouts->channel_layout) {
if (layout_tag == layouts->layout_tag) {
codec->channel_layout = layouts->channel_layout;
@@ -478,8 +479,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, 8);
}
More information about the ffmpeg-devel
mailing list