summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libavcodec/aac.h9
-rw-r--r--libavcodec/aacdec.c48
-rw-r--r--libavcodec/avcodec.h10
-rw-r--r--libavcodec/version.h2
4 files changed, 68 insertions, 1 deletions
diff --git a/libavcodec/aac.h b/libavcodec/aac.h
index 29ba2f1402..a1e91b09b6 100644
--- a/libavcodec/aac.h
+++ b/libavcodec/aac.h
@@ -304,6 +304,15 @@ typedef struct {
float *output_data[MAX_CHANNELS]; ///< Points to each element's 'ret' buffer (PCM output).
/** @} */
+
+ /**
+ * @name Japanese DTV specific extension
+ * @{
+ */
+ int enable_jp_dmono; ///< enable japanese DTV specific 'dual mono'
+ int dmono_mode; ///< select the channel to decode in dual mono.
+ /** @} */
+
DECLARE_ALIGNED(32, float, temp)[128];
OutputConfiguration oc[2];
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)
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index ddf785e68a..8e3eaecd16 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -927,6 +927,16 @@ enum AVPacketSideDataType {
* @endcode
*/
AV_PKT_DATA_SKIP_SAMPLES=70,
+
+ /**
+ * An AV_PKT_DATA_JP_DUALMONO side data packet indicates that
+ * the packet may contain "dual mono" audio specific to Japanese DTV
+ * and if it is true, recommends only the selected channel to be used.
+ * @code
+ * u8 selected channels (0=mail/left, 1=sub/right, 2=both)
+ * @endcode
+ */
+ AV_PKT_DATA_JP_DUALMONO,
};
typedef struct AVPacket {
diff --git a/libavcodec/version.h b/libavcodec/version.h
index a2e231bf7f..3349789af3 100644
--- a/libavcodec/version.h
+++ b/libavcodec/version.h
@@ -27,7 +27,7 @@
*/
#define LIBAVCODEC_VERSION_MAJOR 54
-#define LIBAVCODEC_VERSION_MINOR 55
+#define LIBAVCODEC_VERSION_MINOR 56
#define LIBAVCODEC_VERSION_MICRO 100
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \