Additionally, support Japanese DTV version which uses the different
coefficiency from the AAC standard. (ref. ARIB STD-B21 6.2.1)

Signed-off-by: Akihiro Tsukada <[email protected]>
---
 libavcodec/aacdec.c     |   75 +++++++++++++++++++++++++++++++++++++++++++++-
 libavcodec/mpeg4audio.h |    3 ++
 2 files changed, 76 insertions(+), 2 deletions(-)

diff --git a/libavcodec/aacdec.c b/libavcodec/aacdec.c
index 24b3702..3a01cc7 100644
--- a/libavcodec/aacdec.c
+++ b/libavcodec/aacdec.c
@@ -588,8 +588,13 @@ static int decode_pce(AVCodecContext *avctx, 
MPEG4AudioConfig *m4ac,
     if (get_bits1(gb))
         skip_bits(gb, 4); // stereo_mixdown_tag
 
-    if (get_bits1(gb))
-        skip_bits(gb, 3); // mixdown_coeff_index and pseudo_surround
+    if (get_bits1(gb)) { // mixdown_coeff_index and pseudo_surround
+        m4ac->dmatrix_idx = get_bits(gb, 2);
+        m4ac->p_surround = get_bits1(gb);
+    } else {
+        m4ac->dmatrix_idx = -1;
+        m4ac->p_surround = 0;
+    }
 
     decode_channel_map(layout_map       , AAC_CHANNEL_FRONT, gb, num_front);
     tags = num_front;
@@ -2371,6 +2376,67 @@ static int parse_adts_frame_header(AACContext *ac, 
GetBitContext *gb)
     return size;
 }
 
+/**
+ * Matrix mixdown of 5ch/5.1ch audio into mono/stereo. reference: 8.5.3
+ *    (Japanse DTV reference: ARIB STD-B21 table 6-DM1, 6-DM2)
+ */
+static void aac_downmix5ch(AVCodecContext *avctx, AACContext *ac)
+{
+    static const float coef[4] = {M_SQRT1_2, 0.5, 0.5 * M_SQRT1_2, 0.0};
+    float a, k;
+    float *l, *r, *c, *ls, *rs;
+    int i;
+    int have_lfe;
+
+    avctx->channels = avctx->request_channels;
+    have_lfe = !!(ac->oc[1].channel_layout & AV_CH_LOW_FREQUENCY);
+
+    k = (ac->oc[1].m4ac.dmatrix_idx >= 0) ?
+            coef[ac->oc[1].m4ac.dmatrix_idx] : coef[0];
+
+    l = ac->output_data[0];
+    r = ac->output_data[1];
+    c = ac->output_data[2];
+    ls = ac->output_data[3 + have_lfe];
+    rs = ac->output_data[4 + have_lfe];
+
+    /* 5[.1]ch -> mono */
+    if (avctx->request_channels == 1) {
+        a = 1.0 / (3.0 + 2.0 * k);
+        for (i = 0; i < 1024; i++)
+            ac->output_data[0][i] = a * (*(l++) + *(c++) + *(r++)
+                                    + k * (*(ls++) + *(rs++)));
+        avctx->channels = 1;
+        avctx->channel_layout = AV_CH_LAYOUT_MONO;
+        return;
+    }
+
+    /* 5[.1]ch -> stereo */
+
+    if (ac->jp_dtv_mode)
+        a = M_SQRT1_2;
+    else if (ac->oc[1].m4ac.p_surround)
+        a = 1.0 / (1.0 + M_SQRT1_2 + 2.0 * k);
+    else
+        a = 1.0 / (1.0 + M_SQRT1_2 + k);
+
+    if (!ac->oc[1].m4ac.p_surround) {
+        for (i = 0; i < 1024; i++) {
+            ac->output_data[0][i] = a * (*l + M_SQRT1_2 * *c + k * *ls);
+            ac->output_data[1][i] = a * (*r + M_SQRT1_2 * *c + k * *rs);
+            l++; r++; c++; ls++; rs++;
+        }
+    } else {
+        for (i = 0; i < 1024; i++) {
+            ac->output_data[0][i] = a * (*l + M_SQRT1_2 * *c - k * (*ls + 
*rs));
+            ac->output_data[1][i] = a * (*r + M_SQRT1_2 * *c + k * (*ls + 
*rs));
+            l++; r++; c++; ls++; rs++;
+        }
+    }
+    avctx->channels = 2;
+    avctx->channel_layout = AV_CH_LAYOUT_STEREO;
+}
+
 static int aac_decode_frame_int(AVCodecContext *avctx, void *data,
                                 int *got_frame_ptr, GetBitContext *gb)
 {
@@ -2492,6 +2558,11 @@ 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;
 
+    if (avctx->request_channels <= 2 &&
+        (ac->oc[1].channel_layout == AV_CH_LAYOUT_5POINT0 ||
+         ac->oc[1].channel_layout == AV_CH_LAYOUT_5POINT1))
+       aac_downmix5ch(avctx, ac);
+
     /* for dual-mono audio (SCE + SCE) */
     is_dmono = ac->jp_dtv_mode && sce_count == 2 &&
                ac->oc[1].channel_layout == (AV_CH_FRONT_LEFT | 
AV_CH_FRONT_RIGHT);
diff --git a/libavcodec/mpeg4audio.h b/libavcodec/mpeg4audio.h
index 7560f3f..f89fc3f 100644
--- a/libavcodec/mpeg4audio.h
+++ b/libavcodec/mpeg4audio.h
@@ -38,6 +38,9 @@ typedef struct {
     int ext_chan_config;
     int channels;
     int ps;  ///< -1 implicit, 1 presence
+
+    int dmatrix_idx; ///< index of the coef. of matrix downmix, or -1 for none
+    int p_surround;  ///< pseudo surround enabled. 1: enabled
 } MPEG4AudioConfig;
 
 extern const int avpriv_mpeg4audio_sample_rates[16];
-- 
1.7.7.6

_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to