aboutsummaryrefslogtreecommitdiffstats
path: root/libavcodec/aacdec.c
diff options
context:
space:
mode:
authorAkihiro Tsukada <atsukada@users.sourceforge.net>2012-08-25 20:30:54 +0900
committerMichael Niedermayer <michaelni@gmx.at>2012-09-15 03:50:04 +0200
commitc3c646a868b46f60c2761c9fc8295438868a5df2 (patch)
tree48f56f462e7c7235c4bb5777f5184ceeaf2c0f61 /libavcodec/aacdec.c
parent75d34864d16fbf02928c319134bd94a7a7752092 (diff)
downloadffmpeg-c3c646a868b46f60c2761c9fc8295438868a5df2.tar.gz
aacdec: add support for dual mono in Japanese DTV
Japanese DTV uses some non standard extensions in AAC audio. One example is 'dual mono', which combines two independent audio into one stereo stream, storing them in left and right channels respectively. Historically, dual mono audio has been used for multi-lingual audio, one for local/native language, and another for english, and usually the "main" (local language) channel should be output without any user interactions. The frames of those dual mono audio are allowed to set ADTS channel_config field to 0, and just contain two SCE's *WITHOUT* PCE, which is a non standard extension by Japanese DTV standard. (ref. ARIB STD-B32 PartII 5.2.3) This patch adds an AVPacket side data, AV_PKT_DATA_JP_DUALMONO, which indicates that the AVPacket is likely to contain an audio frame with the above dual mono extension, and has the parameter to specify the desired channel selection in that case. It also makes aacdec to detect dual mono and output just the desired channel when this side data is attached. Signed-off-by: Akihiro Tsukada <atsukada@users.sourceforge.net> Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavcodec/aacdec.c')
-rw-r--r--libavcodec/aacdec.c48
1 files changed, 48 insertions, 0 deletions
diff --git a/libavcodec/aacdec.c b/libavcodec/aacdec.c
index f58e052257..62df283b78 100644
--- a/libavcodec/aacdec.c
+++ b/libavcodec/aacdec.c
@@ -2375,6 +2375,21 @@ static int parse_adts_frame_header(AACContext *ac, GetBitContext *gb)
return -7;
} else {
ac->oc[1].m4ac.chan_config = 0;
+ /**
+ * dual mono frames in Japanese DTV can have chan_config 0
+ * WITHOUT specifying PCE.
+ * thus, set dual mono as default.
+ */
+ if (ac->enable_jp_dmono && ac->oc[0].status == OC_NONE) {
+ layout_map_tags = 2;
+ layout_map[0][0] = layout_map[1][0] = TYPE_SCE;
+ layout_map[0][2] = layout_map[1][2] = AAC_CHANNEL_FRONT;
+ layout_map[0][1] = 0;
+ layout_map[1][1] = 1;
+ if (output_configure(ac, layout_map, layout_map_tags,
+ 0, OC_TRIAL_FRAME))
+ return -7;
+ }
}
ac->oc[1].m4ac.sample_rate = hdr_info.sample_rate;
ac->oc[1].m4ac.sampling_index = hdr_info.sampling_index;
@@ -2399,6 +2414,8 @@ static int aac_decode_frame_int(AVCodecContext *avctx, void *data,
enum RawDataBlockType elem_type, elem_type_prev = TYPE_END;
int err, elem_id;
int samples = 0, multiplier, audio_found = 0, pce_found = 0;
+ int is_dmono, sce_count = 0;
+ float *tmp = NULL;
if (show_bits(gb, 12) == 0xfff) {
if (parse_adts_frame_header(ac, gb) < 0) {
@@ -2433,6 +2450,7 @@ static int aac_decode_frame_int(AVCodecContext *avctx, void *data,
case TYPE_SCE:
err = decode_ics(ac, &che->ch[0], gb, 0, 0);
audio_found = 1;
+ sce_count++;
break;
case TYPE_CPE:
@@ -2511,6 +2529,20 @@ static int aac_decode_frame_int(AVCodecContext *avctx, void *data,
multiplier = (ac->oc[1].m4ac.sbr == 1) ? ac->oc[1].m4ac.ext_sample_rate > ac->oc[1].m4ac.sample_rate : 0;
samples <<= multiplier;
+ /* for dual-mono audio (SCE + SCE) */
+ is_dmono = ac->enable_jp_dmono && sce_count == 2 &&
+ ac->oc[1].channel_layout == (AV_CH_FRONT_LEFT | AV_CH_FRONT_RIGHT);
+
+ if (is_dmono) {
+ if (ac->dmono_mode == 0) {
+ tmp = ac->output_data[1];
+ ac->output_data[1] = ac->output_data[0];
+ } else if (ac->dmono_mode == 1) {
+ tmp = ac->output_data[0];
+ ac->output_data[0] = ac->output_data[1];
+ }
+ }
+
if (samples) {
/* get output buffer */
ac->frame.nb_samples = samples;
@@ -2533,6 +2565,13 @@ static int aac_decode_frame_int(AVCodecContext *avctx, void *data,
}
*got_frame_ptr = !!samples;
+ if (is_dmono) {
+ if (ac->dmono_mode == 0)
+ ac->output_data[1] = tmp;
+ else if (ac->dmono_mode == 1)
+ ac->output_data[0] = tmp;
+ }
+
if (ac->oc[1].status && audio_found) {
avctx->sample_rate = ac->oc[1].m4ac.sample_rate << multiplier;
avctx->frame_size = samples;
@@ -2565,6 +2604,10 @@ static int aac_decode_frame(AVCodecContext *avctx, void *data,
const uint8_t *new_extradata = av_packet_get_side_data(avpkt,
AV_PKT_DATA_NEW_EXTRADATA,
&new_extradata_size);
+ int jp_dualmono_size;
+ const uint8_t *jp_dualmono = av_packet_get_side_data(avpkt,
+ AV_PKT_DATA_JP_DUALMONO,
+ &jp_dualmono_size);
if (new_extradata && 0) {
av_free(avctx->extradata);
@@ -2583,6 +2626,11 @@ static int aac_decode_frame(AVCodecContext *avctx, void *data,
}
}
+ ac->enable_jp_dmono = !!jp_dualmono;
+ ac->dmono_mode = 0;
+ if (jp_dualmono && jp_dualmono_size > 0)
+ ac->dmono_mode = *jp_dualmono;
+
init_get_bits(&gb, buf, buf_size * 8);
if ((err = aac_decode_frame_int(avctx, data, got_frame_ptr, &gb, avpkt)) < 0)