[FFmpeg-devel] [PATCH v3 3/3] avcodec/aacdec: Translate PCE to avutil channel layouts

pkv.stream pkv.stream at gmail.com
Wed Oct 24 23:03:35 EEST 2018


Patch updated ; passes all FATE tests.

Comments from Alex Converse review incorporated (much thanks to him).


-------------- next part --------------
From 168411206bc07d6a74097c52b3b88063591787ae Mon Sep 17 00:00:00 2001
From: pkviet <pkv.stream at gmail.com>
Date: Wed, 24 Oct 2018 06:31:52 +0200
Subject: [PATCH 3/3] avcodec/aacdec: Translate pce to avutil channel_layout

This commit makes additions to the capabilties of native aac
decoder to translate pce to ffmpeg channel layouts.
For all pce generated by the native aac encoder a table is used.
For more general pce (up to 22 channels) a custom layout is built
when chan_config == 0.

Signed-off-by: pkviet <pkv.stream at gmail.com>
---
 libavcodec/aacdec_template.c | 229 ++++++++++++++++++++++++++++++++++++++++++-
 libavcodec/aacdectab.h       | 126 ++++++++++++++++++++++++
 2 files changed, 351 insertions(+), 4 deletions(-)

diff --git a/libavcodec/aacdec_template.c b/libavcodec/aacdec_template.c
index dce6035d67..c1748d3673 100644
--- a/libavcodec/aacdec_template.c
+++ b/libavcodec/aacdec_template.c
@@ -155,6 +155,34 @@ static av_cold int che_configure(AACContext *ac,
     return 0;
 }
 
+static uint8_t *pce_reorder_map(uint64_t layout, int channels)
+{
+    if (layout == AV_CH_LAYOUT_7POINT1_WIDE || layout == AV_CH_LAYOUT_7POINT1 ||
+        layout == AV_CH_LAYOUT_7POINT1_WIDE_BACK)
+        return aac_chan_maps[7];
+    if (layout == AV_CH_LAYOUT_6POINT1 || layout == AV_CH_LAYOUT_6POINT1_BACK ||
+        layout == AV_CH_LAYOUT_6POINT1_FRONT)
+        return aac_chan_maps[6];
+    if (layout == AV_CH_LAYOUT_5POINT1 || layout == AV_CH_LAYOUT_5POINT1_BACK)
+        return aac_chan_maps[5];
+    if (layout == AV_CH_LAYOUT_4POINT1 || layout == AV_CH_LAYOUT_5POINT0_BACK)
+        return aac_chan_maps[4];
+    if (layout == AV_CH_LAYOUT_3POINT1 || layout == AV_CH_LAYOUT_4POINT0)
+        return aac_chan_maps[3];
+    return normal_chan_maps[channels - 1];
+}
+
+static int has_CCE(AVCodecContext *avctx)
+{
+    AACContext *ac = avctx->priv_data;
+    int         i;
+    for (i = 0; i < MAX_ELEM_ID * 4; i++) {
+        if (ac->oc[1].layout_map[i][0] == TYPE_CCE)
+            return 1;
+    }
+    return 0;
+}
+
 static int frame_configure_elements(AVCodecContext *avctx)
 {
     AACContext *ac = avctx->priv_data;
@@ -180,10 +208,17 @@ static int frame_configure_elements(AVCodecContext *avctx)
     if ((ret = ff_get_buffer(avctx, ac->frame, 0)) < 0)
         return ret;
 
+    /* reorder channels in case pce table was used with LFE channel */
+    uint8_t reorder[8] = {0, 1, 2, 3, 4, 5, 6, 7};
+    if (ac->oc[1].m4ac.chan_config == 0 && avctx->channels < 9
+        && avctx->channels > 4 && !has_CCE(avctx))
+        memcpy(reorder, pce_reorder_map(ac->oc[1].channel_layout, avctx->channels),
+               avctx->channels * sizeof(uint8_t));
     /* map output channel pointers to AVFrame data */
     for (ch = 0; ch < avctx->channels; ch++) {
+        int ch_remapped = avctx->channels < 9 ? reorder[ch] : ch;
         if (ac->output_element[ch])
-            ac->output_element[ch]->ret = (INTFLOAT *)ac->frame->extended_data[ch];
+            ac->output_element[ch]->ret = (INTFLOAT *)ac->frame->extended_data[ch_remapped];
     }
 
     return 0;
@@ -257,13 +292,193 @@ static int count_paired_channels(uint8_t (*layout_map)[3], int tags, int pos,
     return num_pos_channels;
 }
 
-static uint64_t sniff_channel_order(uint8_t (*layout_map)[3], int tags)
+static int count_channels_per_type(uint8_t (*layout_map)[3], int tags, int pos, enum RawDataBlockType type)
+{
+    int num_pos_channels = 0;
+    int i;
+    for (i = 0; i < tags; i++) {
+        if (layout_map[i][2] != pos)
+            continue;
+        if (layout_map[i][0] == type) {
+            if (type == TYPE_CPE)
+                num_pos_channels += 2;
+            if (type == TYPE_SCE || type == TYPE_LFE || type == TYPE_CCE) // used to detect CCE
+                num_pos_channels += 1;
+        }
+    }
+
+    return num_pos_channels;
+}
+
+static uint64_t convert_layout_map_to_av_layout(uint8_t layout_map[MAX_ELEM_ID * 4][3])
+{
+    int i, config;
+    config = 0;
+    // look up pce table for channel layout correspondence used by native encoder and decoder
+    for (i = 1; i < PCE_LAYOUT_NBR; i++) {
+        if (memcmp(layout_map, pce_channel_layout_map[i], sizeof(uint8_t) * 3 * PCE_MAX_TAG) == 0) {
+            config = i;
+            break;
+        }
+    }
+    return pce_channel_layout_list[config];
+}
+
+static uint64_t sniff_channel_order(AACContext *ac, uint8_t (*layout_map)[3], int tags)
 {
     int i, n, total_non_cc_elements;
     struct elem_to_channel e2c_vec[4 * MAX_ELEM_ID] = { { 0 } };
     int num_front_channels, num_side_channels, num_back_channels;
+    int num_front_channels_SCE, num_front_channels_CPE, num_LFE_channels;
+    int num_side_channels_CPE, num_back_channels_SCE, num_back_channels_CPE;
+    int has_CCE_channels;
+    int channels;
     uint64_t layout;
 
+    num_front_channels_SCE = count_channels_per_type(layout_map, tags, AAC_CHANNEL_FRONT, TYPE_SCE);
+    num_back_channels_SCE  = count_channels_per_type(layout_map, tags, AAC_CHANNEL_BACK, TYPE_SCE);
+    num_front_channels_CPE = count_channels_per_type(layout_map, tags, AAC_CHANNEL_FRONT, TYPE_CPE);
+    num_side_channels_CPE  = count_channels_per_type(layout_map, tags, AAC_CHANNEL_SIDE, TYPE_CPE);
+    num_back_channels_CPE  = count_channels_per_type(layout_map, tags, AAC_CHANNEL_BACK, TYPE_CPE);
+    num_LFE_channels       = count_channels_per_type(layout_map, tags, AAC_CHANNEL_LFE, TYPE_LFE);
+    has_CCE_channels       = count_channels_per_type(layout_map, tags, AAC_CHANNEL_CC, TYPE_CCE);
+    channels = num_front_channels_SCE + num_back_channels_SCE + num_LFE_channels + num_front_channels_CPE +
+               num_side_channels_CPE + num_back_channels_CPE;
+    if (ac->oc[1].m4ac.chan_config == 0 && !has_CCE_channels) {
+        layout = 0;
+        // first use table to find layout
+        if (PCE_MAX_TAG >= tags)
+            layout = convert_layout_map_to_av_layout(layout_map);
+        if (layout > 0) {
+            char buf[64];
+            av_get_channel_layout_string(buf, sizeof(buf), -1, layout);
+            av_log(ac->avctx, AV_LOG_WARNING, "Using PCE table: channel layout "
+                   "decoded as %s (%#llx)\n", buf, layout);
+            return layout;
+        }
+        /* Build a custom layout directly from pce (CC elements are not taken into account).
+         * Channel_layout.h lists up to 24 indivudal channel masks of which we use
+         * 22, discounting AV_CH_STEREO_LEFT and AV_CH_STEREO_RIGHT
+         */
+        if (channels > 22)
+            goto fallback;
+        switch (num_LFE_channels) {
+        case 1:
+            layout |= AV_CH_LOW_FREQUENCY;
+            break;
+        case 2:
+            layout |= AV_CH_LOW_FREQUENCY | AV_CH_LOW_FREQUENCY_2;
+            break;
+        case 0:
+            break;
+        default:
+            goto fallback;
+        }
+        switch (num_front_channels_SCE) {
+        case 1:
+            layout |= AV_CH_FRONT_CENTER;
+            break;
+        case 2:
+            layout |= AV_CH_FRONT_CENTER | AV_CH_TOP_FRONT_CENTER;
+            break;
+        case 0:
+            break;
+        default:
+            goto fallback;
+        }
+        switch (num_front_channels_CPE) {
+        case 2:
+            layout |= AV_CH_FRONT_LEFT | AV_CH_FRONT_RIGHT;
+            break;
+        case 4:
+            layout |= AV_CH_FRONT_LEFT | AV_CH_FRONT_RIGHT | AV_CH_FRONT_LEFT_OF_CENTER |
+                      AV_CH_FRONT_RIGHT_OF_CENTER;
+            break;
+        case 6:
+            layout |= AV_CH_FRONT_LEFT | AV_CH_FRONT_RIGHT | AV_CH_FRONT_LEFT_OF_CENTER |
+                      AV_CH_FRONT_RIGHT_OF_CENTER | AV_CH_TOP_FRONT_LEFT | AV_CH_TOP_FRONT_RIGHT;
+            break;
+        case 0:
+            break;
+        default:
+            goto fallback;
+        }
+        switch (num_back_channels_SCE) {
+        case 1:
+            layout |= AV_CH_BACK_CENTER;
+            break;
+        case 2:
+            layout |= AV_CH_BACK_CENTER | AV_CH_TOP_BACK_CENTER;
+            break;
+        case 0:
+            break;
+        default:
+            goto fallback;
+        }
+        switch (num_back_channels_CPE) {
+        case 2:
+            layout |= AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT;
+            break;
+        case 4:
+            layout |= AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT | AV_CH_TOP_BACK_LEFT | AV_CH_TOP_BACK_RIGHT;
+            break;
+        case 0:
+            break;
+        default:
+            goto fallback;
+        }
+        switch (num_side_channels_CPE) {
+        case 2:
+            layout |= AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT;
+            break;
+        case 4:
+            layout |= AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT | AV_CH_WIDE_LEFT | AV_CH_WIDE_RIGHT;
+            break;
+        case 6:
+            layout |= AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT | AV_CH_WIDE_LEFT | AV_CH_WIDE_RIGHT |
+                      AV_CH_SURROUND_DIRECT_LEFT | AV_CH_SURROUND_DIRECT_RIGHT;
+        case 0:
+            break;
+        default:
+            goto fallback;
+        }
+        // fix for layout 3.0 (reorders layout_map from [SCE, CPE] to [CPE, SCE])
+        // because the table has the correspondence 'Front: [CPE, SCE]' to '3.0'
+        if (layout == AV_CH_LAYOUT_SURROUND) {
+            layout_map[0][0] = TYPE_CPE;
+            layout_map[0][1] = 0;
+            layout_map[0][2] = AAC_CHANNEL_FRONT;
+            layout_map[1][0] = TYPE_SCE;
+            layout_map[1][1] = 0;
+            layout_map[1][2] = AAC_CHANNEL_FRONT;
+        }
+        /* 'fix' for layout 0xcf (this is to be consistent with previous code,
+         *  and fate-test, see 'fallback' below); this changes the channel ordering.
+         */
+        if (layout == (AV_CH_LAYOUT_3POINT1 | AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER)) {
+            layout_map[0][0] = TYPE_CPE;
+            layout_map[0][1] = 1;
+            layout_map[0][2] = AAC_CHANNEL_FRONT;
+            layout_map[1][0] = TYPE_SCE;
+            layout_map[1][1] = 0;
+            layout_map[1][2] = AAC_CHANNEL_FRONT;
+            layout_map[2][0] = TYPE_LFE;
+            layout_map[2][1] = 0;
+            layout_map[2][2] = AAC_CHANNEL_LFE;
+            layout_map[3][0] = TYPE_CPE;
+            layout_map[3][1] = 0;
+            layout_map[3][2] = AAC_CHANNEL_FRONT;
+        }
+        if (layout) {
+            char buf[64];
+            av_get_channel_layout_string(buf, sizeof(buf), -1, layout);
+            av_log(ac->avctx, AV_LOG_WARNING, "Decoding PCE: "
+                   "using custom channel layout %s (%#llx)\n", buf, layout);
+            return layout;
+        }
+    }
+
+fallback:
     if (FF_ARRAY_ELEMS(e2c_vec) < tags)
         return 0;
 
@@ -463,7 +678,7 @@ static int output_configure(AACContext *ac,
     // Try to sniff a reasonable channel order, otherwise output the
     // channels in the order the PCE declared them.
     if (avctx->request_channel_layout != AV_CH_LAYOUT_NATIVE)
-        layout = sniff_channel_order(layout_map, tags);
+        layout = sniff_channel_order(ac, layout_map, tags);
     for (i = 0; i < tags; i++) {
         int type =     layout_map[i][0];
         int id =       layout_map[i][1];
@@ -738,7 +953,7 @@ static int decode_pce(AVCodecContext *avctx, MPEG4AudioConfig *m4ac,
     int num_front, num_side, num_back, num_lfe, num_assoc_data, num_cc;
     int sampling_index;
     int comment_len;
-    int tags;
+    int i, j, tags;
 
     skip_bits(gb, 2);  // object_type
 
@@ -781,6 +996,12 @@ static int decode_pce(AVCodecContext *avctx, MPEG4AudioConfig *m4ac,
     decode_channel_map(layout_map + tags, AAC_CHANNEL_CC,    gb, num_cc);
     tags += num_cc;
 
+    /* zeroes layout_map beyond tags*/
+    for (i = tags; i < MAX_ELEM_ID * 4; i++) {
+        for (j = 0; j < 3; j++)
+                layout_map[i][j] = 0;
+    }
+
     relative_align_get_bits(gb, byte_align_ref);
 
     /* comment field, first byte is length */
diff --git a/libavcodec/aacdectab.h b/libavcodec/aacdectab.h
index baf51a74bf..17df04469c 100644
--- a/libavcodec/aacdectab.h
+++ b/libavcodec/aacdectab.h
@@ -35,6 +35,7 @@
 
 #include <stdint.h>
 
+#define AAC_MAX_CHANNELS 8
 static const int8_t tags_per_config[16] = { 0, 1, 1, 2, 3, 3, 4, 5, 0, 0, 0, 4, 5, 0, 5, 0 };
 
 static const uint8_t aac_channel_layout_map[16][5][3] = {
@@ -71,4 +72,129 @@ static const uint64_t aac_channel_layout[16] = {
     /* AV_CH_LAYOUT_7POINT1_TOP, */
 };
 
+#define PCE_LAYOUT_NBR 35
+#define PCE_MAX_TAG 10
+
+/* number of tags for the pce_channel_layout_map table */
+static const int8_t tags_pce_config[PCE_LAYOUT_NBR] = {0, 10, 9, 8, 7, 8, 7, 6, 6, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2,  1, 1};
+
+static const uint8_t pce_channel_layout_map[PCE_LAYOUT_NBR][10][3] = {
+    { { 0, } },
+    { { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_SCE, 1, AAC_CHANNEL_FRONT }, { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 1, AAC_CHANNEL_FRONT }, { TYPE_CPE, 2, AAC_CHANNEL_SIDE }, { TYPE_CPE, 3, AAC_CHANNEL_SIDE }, { TYPE_CPE, 4, AAC_CHANNEL_BACK }, { TYPE_CPE, 5, AAC_CHANNEL_BACK }, { TYPE_SCE, 2, AAC_CHANNEL_BACK }, { TYPE_SCE, 3, AAC_CHANNEL_BACK }, },//AV_CH_LAYOUT_HEXADECAGONAL
+    { { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_SCE, 1, AAC_CHANNEL_FRONT }, { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 1, AAC_CHANNEL_FRONT }, { TYPE_CPE, 2, AAC_CHANNEL_SIDE }, { TYPE_CPE, 3, AAC_CHANNEL_SIDE }, { TYPE_CPE, 4, AAC_CHANNEL_BACK }, { TYPE_CPE, 5, AAC_CHANNEL_BACK }, { TYPE_SCE, 2, AAC_CHANNEL_BACK }, },// 0x3FF37, 15ch
+    { { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_SCE, 1, AAC_CHANNEL_FRONT }, { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 1, AAC_CHANNEL_FRONT }, { TYPE_CPE, 2, AAC_CHANNEL_SIDE }, { TYPE_CPE, 3, AAC_CHANNEL_SIDE }, { TYPE_CPE, 4, AAC_CHANNEL_BACK }, { TYPE_CPE, 5, AAC_CHANNEL_BACK }, },// 0x2FF37, 14ch
+    { { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 1, AAC_CHANNEL_FRONT }, { TYPE_CPE, 2, AAC_CHANNEL_SIDE }, { TYPE_CPE, 3, AAC_CHANNEL_SIDE }, { TYPE_CPE, 4, AAC_CHANNEL_BACK }, { TYPE_CPE, 5, AAC_CHANNEL_BACK }, },// 0x17F37, 13ch
+    { { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_SCE, 1, AAC_CHANNEL_FRONT }, { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 1, AAC_CHANNEL_FRONT }, { TYPE_CPE, 2, AAC_CHANNEL_SIDE }, { TYPE_SCE, 2, AAC_CHANNEL_SIDE }, { TYPE_CPE, 3, AAC_CHANNEL_BACK }, { TYPE_SCE, 3, AAC_CHANNEL_BACK }, },// 0x7F37, 12ch
+    { { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_SCE, 1, AAC_CHANNEL_FRONT }, { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 1, AAC_CHANNEL_FRONT }, { TYPE_CPE, 2, AAC_CHANNEL_SIDE }, { TYPE_SCE, 2, AAC_CHANNEL_SIDE }, { TYPE_CPE, 3, AAC_CHANNEL_BACK }, },// 0x5F37, 11ch
+    { { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 1, AAC_CHANNEL_FRONT }, { TYPE_CPE, 2, AAC_CHANNEL_SIDE }, { TYPE_SCE, 0, AAC_CHANNEL_SIDE }, { TYPE_CPE, 3, AAC_CHANNEL_BACK }, { TYPE_SCE, 1, AAC_CHANNEL_BACK }, },//0xFF3, 10ch
+    { { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_SCE, 1, AAC_CHANNEL_SIDE }, { TYPE_CPE, 1, AAC_CHANNEL_SIDE }, { TYPE_CPE, 2, AAC_CHANNEL_BACK }, { TYPE_SCE, 2, AAC_CHANNEL_BACK }, },//AV_CH_LAYOUT_OCTAGONAL | AV_CH_TOP_CENTER , 9 ch
+    { { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 1, AAC_CHANNEL_SIDE }, { TYPE_CPE, 2, AAC_CHANNEL_BACK }, { TYPE_SCE, 1, AAC_CHANNEL_BACK }, },//AV_CH_LAYOUT_OCTAGONAL
+    { { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 1, AAC_CHANNEL_SIDE }, { TYPE_CPE, 2, AAC_CHANNEL_BACK }, { TYPE_LFE, 0, AAC_CHANNEL_LFE }, },//AV_CH_LAYOUT_7POINT1
+    { { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 1, AAC_CHANNEL_FRONT }, { TYPE_CPE, 2, AAC_CHANNEL_SIDE }, { TYPE_LFE, 0, AAC_CHANNEL_LFE }, },//AV_CH_LAYOUT_7POINT1_WIDE
+    { { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 1, AAC_CHANNEL_FRONT }, { TYPE_CPE, 2, AAC_CHANNEL_BACK }, { TYPE_LFE, 0, AAC_CHANNEL_LFE }, },//AV_CH_LAYOUT_7POINT1_WIDE_BACK
+    { { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 1, AAC_CHANNEL_SIDE }, { TYPE_SCE, 1, AAC_CHANNEL_BACK }, { TYPE_LFE, 0, AAC_CHANNEL_LFE }, },//AV_CH_LAYOUT_6POINT1
+    { { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 1, AAC_CHANNEL_BACK }, { TYPE_SCE, 1, AAC_CHANNEL_BACK }, { TYPE_LFE, 0, AAC_CHANNEL_LFE }, },//AV_CH_LAYOUT_6POINT1_BACK
+    { { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 1, AAC_CHANNEL_SIDE }, { TYPE_CPE, 2, AAC_CHANNEL_BACK }, },//AV_CH_LAYOUT_7POINT0
+    { { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 1, AAC_CHANNEL_FRONT }, { TYPE_CPE, 2, AAC_CHANNEL_SIDE }, },//AV_CH_LAYOUT_7POINT0_FRONT
+    { { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 1, AAC_CHANNEL_BACK }, { TYPE_SCE, 1, AAC_CHANNEL_BACK }, },//AV_CH_LAYOUT_HEXAGONAL
+    { { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 1, AAC_CHANNEL_FRONT }, { TYPE_CPE, 2, AAC_CHANNEL_SIDE }, { TYPE_LFE, 0, AAC_CHANNEL_LFE }, },//AV_CH_LAYOUT_6POINT1_FRONT
+    { { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 1, AAC_CHANNEL_SIDE }, { TYPE_SCE, 1, AAC_CHANNEL_BACK }, },//AV_CH_LAYOUT_6POINT0
+    { { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 1, AAC_CHANNEL_SIDE }, { TYPE_LFE, 0, AAC_CHANNEL_LFE }, },//AV_CH_LAYOUT_5POINT1
+    { { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 1, AAC_CHANNEL_BACK },  { TYPE_LFE, 0, AAC_CHANNEL_LFE }, },//AV_CH_LAYOUT_5POINT1_BACK
+    { { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_SCE, 1, AAC_CHANNEL_BACK }, { TYPE_LFE, 0, AAC_CHANNEL_LFE }, },//AV_CH_LAYOUT_4POINT1
+    { { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 1, AAC_CHANNEL_FRONT }, { TYPE_CPE, 2, AAC_CHANNEL_SIDE }, },//AV_CH_LAYOUT_6POINT0_FRONT
+    { { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 1, AAC_CHANNEL_SIDE }, },//AV_CH_LAYOUT_5POINT0
+    { { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 1, AAC_CHANNEL_BACK }, },//AV_CH_LAYOUT_5POINT0_BACK
+    { { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_SCE, 1, AAC_CHANNEL_BACK }, },//AV_CH_LAYOUT_4POINT0
+    { { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_LFE, 0, AAC_CHANNEL_LFE }, },//AV_CH_LAYOUT_3POINT1
+    { { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 1, AAC_CHANNEL_BACK }, },//AV_CH_LAYOUT_QUAD
+    { { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 1, AAC_CHANNEL_SIDE }, },//AV_CH_LAYOUT_2_2
+    { { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_LFE, 0, AAC_CHANNEL_LFE }, },  //AV_CH_LAYOUT_2POINT1
+    { { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_SCE, 0, AAC_CHANNEL_BACK }, }, //AV_CH_LAYOUT_2_1
+    { { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, },//AV_CH_LAYOUT_SURROUND
+    { { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, }, //AV_CH_LAYOUT_STEREO
+    { { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, }, //AV_CH_LAYOUT_MONO
+};
+
+/* list of channel layouts supported by the pce encoder /decoder table */
+static const uint64_t pce_channel_layout_list[PCE_LAYOUT_NBR] = {
+    0,
+    AV_CH_LAYOUT_HEXADECAGONAL,
+    AV_CH_LAYOUT_OCTAGONAL | AV_CH_TOP_CENTER | AV_CH_TOP_FRONT_LEFT |
+    AV_CH_TOP_FRONT_RIGHT | AV_CH_TOP_FRONT_CENTER | AV_CH_TOP_BACK_CENTER |
+    AV_CH_TOP_BACK_LEFT | AV_CH_TOP_BACK_RIGHT,
+    AV_CH_LAYOUT_OCTAGONAL | AV_CH_TOP_CENTER | AV_CH_TOP_FRONT_LEFT |
+    AV_CH_TOP_FRONT_RIGHT | AV_CH_TOP_FRONT_CENTER | AV_CH_TOP_BACK_LEFT |
+    AV_CH_TOP_BACK_RIGHT,
+    AV_CH_LAYOUT_OCTAGONAL | AV_CH_TOP_CENTER | AV_CH_TOP_FRONT_LEFT |
+    AV_CH_TOP_FRONT_RIGHT | AV_CH_TOP_FRONT_CENTER | AV_CH_TOP_BACK_CENTER,
+    AV_CH_LAYOUT_OCTAGONAL | AV_CH_TOP_CENTER | AV_CH_TOP_FRONT_LEFT |
+    AV_CH_TOP_FRONT_RIGHT | AV_CH_TOP_FRONT_CENTER,
+    AV_CH_LAYOUT_OCTAGONAL | AV_CH_TOP_CENTER | AV_CH_TOP_FRONT_LEFT | AV_CH_TOP_FRONT_RIGHT,
+    AV_CH_LAYOUT_6POINT0_FRONT | AV_CH_BACK_CENTER | AV_CH_BACK_LEFT |
+    AV_CH_BACK_RIGHT | AV_CH_TOP_CENTER,
+    AV_CH_LAYOUT_OCTAGONAL | AV_CH_TOP_CENTER,
+    AV_CH_LAYOUT_OCTAGONAL,
+    AV_CH_LAYOUT_7POINT1,
+    AV_CH_LAYOUT_7POINT1_WIDE,
+    AV_CH_LAYOUT_7POINT1_WIDE_BACK,
+    AV_CH_LAYOUT_6POINT1,
+    AV_CH_LAYOUT_6POINT1_BACK,
+    AV_CH_LAYOUT_7POINT0,
+    AV_CH_LAYOUT_7POINT0_FRONT,
+    AV_CH_LAYOUT_HEXAGONAL,
+    AV_CH_LAYOUT_6POINT1_FRONT,
+    AV_CH_LAYOUT_6POINT0,
+    AV_CH_LAYOUT_5POINT1,
+    AV_CH_LAYOUT_5POINT1_BACK,
+    AV_CH_LAYOUT_4POINT1,
+    AV_CH_LAYOUT_6POINT0_FRONT,
+    AV_CH_LAYOUT_5POINT0,
+    AV_CH_LAYOUT_5POINT0_BACK,
+    AV_CH_LAYOUT_4POINT0,
+    AV_CH_LAYOUT_3POINT1,
+    AV_CH_LAYOUT_QUAD,
+    AV_CH_LAYOUT_2_2,
+    AV_CH_LAYOUT_2POINT1,
+    AV_CH_LAYOUT_2_1,
+    AV_CH_LAYOUT_SURROUND,
+    AV_CH_LAYOUT_STEREO,
+    AV_CH_LAYOUT_MONO,
+};
+/**
+ * Table to remap channels from libavcodec's default order to AAC order.
+ */
+static const uint8_t aac_chan_maps[AAC_MAX_CHANNELS][AAC_MAX_CHANNELS] = {
+    {0},
+    {0, 1},
+    {2, 0, 1},
+    {2, 0, 1, 3},
+    {2, 0, 1, 3, 4},
+    {2, 0, 1, 4, 5, 3},
+    {2, 0, 1, 4, 5, 6, 3},
+    {2, 0, 1, 6, 7, 4, 5, 3},
+};
+
+static const uint8_t normal_chan_maps[AAC_MAX_CHANNELS][AAC_MAX_CHANNELS] = {
+    {0},
+    {0, 1},
+    {0, 1, 2},
+    {0, 1, 2, 3},
+    {0, 1, 2, 3, 4},
+    {0, 1, 2, 3, 4, 5},
+    {0, 1, 2, 3, 4, 5, 6},
+    {0, 1, 2, 3, 4, 5, 6, 7},
+};
+
+/* Supported layouts without using a PCE */
+static const int64_t aac_normal_chan_layouts[8] = {
+        AV_CH_LAYOUT_MONO,
+        AV_CH_LAYOUT_STEREO,
+        AV_CH_LAYOUT_SURROUND,
+        AV_CH_LAYOUT_4POINT0,
+        AV_CH_LAYOUT_5POINT0_BACK,
+        AV_CH_LAYOUT_5POINT1_BACK,
+        0,
+        AV_CH_LAYOUT_7POINT1,
+};
 #endif /* AVCODEC_AACDECTAB_H */
-- 
2.16.2.windows.1



More information about the ffmpeg-devel mailing list