Browse code

aacenc: support extended channel layouts using PCEs

This commit implements support for PCE (Program Configuration Elements) in the
AAC encoder, and as such allows for encoding of channel layouts not present
in the presets defined by the spec (which only lists the 8 most common ones).

This has been a highly requested feature and is also the first open source encoder
to support this many layouts.

Many thanks to pkviet <pkv.stream@gmail.com> who implemented support for and
verified all channel layouts.

Rostislav Pehlivanov authored on 2016/10/04 03:53:11
Showing 4 changed files
... ...
@@ -10,6 +10,7 @@ version <next>:
10 10
 - Raw AMR-NB and AMR-WB demuxers
11 11
 - TiVo ty/ty+ demuxer
12 12
 - Intel QSV-accelerated MJPEG encoding
13
+- PCE support for extended channel layouts in the AAC encoder
13 14
 
14 15
 
15 16
 version 3.4:
... ...
@@ -50,6 +50,40 @@
50 50
 
51 51
 static AVOnce aac_table_init = AV_ONCE_INIT;
52 52
 
53
+static void put_pce(PutBitContext *pb, AVCodecContext *avctx)
54
+{
55
+    int i, j;
56
+    AACEncContext *s = avctx->priv_data;
57
+    AACPCEInfo *pce = &s->pce;
58
+
59
+    put_bits(pb, 4, 0);
60
+
61
+    put_bits(pb, 2, avctx->profile);
62
+    put_bits(pb, 4, s->samplerate_index);
63
+
64
+    put_bits(pb, 4, pce->num_ele[0]); /* Front */
65
+    put_bits(pb, 4, pce->num_ele[1]); /* Side */
66
+    put_bits(pb, 4, pce->num_ele[2]); /* Back */
67
+    put_bits(pb, 2, pce->num_ele[3]); /* LFE */
68
+    put_bits(pb, 3, 0); /* Assoc data */
69
+    put_bits(pb, 4, 0); /* CCs */
70
+
71
+    put_bits(pb, 1, 0); /* Stereo mixdown */
72
+    put_bits(pb, 1, 0); /* Mono mixdown */
73
+    put_bits(pb, 1, 0); /* Something else */
74
+
75
+    for (i = 0; i < 4; i++) {
76
+        for (j = 0; j < pce->num_ele[i]; j++) {
77
+            if (i < 3)
78
+                put_bits(pb, 1, pce->pairing[i][j]);
79
+            put_bits(pb, 4, pce->index[i][j]);
80
+        }
81
+    }
82
+
83
+    avpriv_align_put_bits(pb);
84
+    put_bits(pb, 8, 0);
85
+}
86
+
53 87
 /**
54 88
  * Make AAC audio config object.
55 89
  * @see 1.6.2.1 "Syntax - AudioSpecificConfig"
... ...
@@ -58,7 +92,7 @@ static void put_audio_specific_config(AVCodecContext *avctx)
58 58
 {
59 59
     PutBitContext pb;
60 60
     AACEncContext *s = avctx->priv_data;
61
-    int channels = s->channels - (s->channels == 8 ? 1 : 0);
61
+    int channels = (!s->needs_pce)*(s->channels - (s->channels == 8 ? 1 : 0));
62 62
 
63 63
     init_put_bits(&pb, avctx->extradata, avctx->extradata_size);
64 64
     put_bits(&pb, 5, s->profile+1); //profile
... ...
@@ -68,6 +102,8 @@ static void put_audio_specific_config(AVCodecContext *avctx)
68 68
     put_bits(&pb, 1, 0); //frame length - 1024 samples
69 69
     put_bits(&pb, 1, 0); //does not depend on core coder
70 70
     put_bits(&pb, 1, 0); //is not extension
71
+    if (s->needs_pce)
72
+        put_pce(&pb, avctx);
71 73
 
72 74
     //Explicitly Mark SBR absent
73 75
     put_bits(&pb, 11, 0x2b7); //sync extension
... ...
@@ -488,7 +524,7 @@ static void copy_input_samples(AACEncContext *s, const AVFrame *frame)
488 488
 {
489 489
     int ch;
490 490
     int end = 2048 + (frame ? frame->nb_samples : 0);
491
-    const uint8_t *channel_map = aac_chan_maps[s->channels - 1];
491
+    const uint8_t *channel_map = s->reorder_map;
492 492
 
493 493
     /* copy and remap input samples */
494 494
     for (ch = 0; ch < s->channels; ch++) {
... ...
@@ -920,16 +956,36 @@ static av_cold int aac_encode_init(AVCodecContext *avctx)
920 920
 
921 921
     /* Constants */
922 922
     s->last_frame_pb_count = 0;
923
-    avctx->extradata_size = 5;
923
+    avctx->extradata_size = 20;
924 924
     avctx->frame_size = 1024;
925 925
     avctx->initial_padding = 1024;
926 926
     s->lambda = avctx->global_quality > 0 ? avctx->global_quality : 120;
927 927
 
928 928
     /* Channel map and unspecified bitrate guessing */
929 929
     s->channels = avctx->channels;
930
-    ERROR_IF(s->channels > AAC_MAX_CHANNELS || s->channels == 7,
931
-             "Unsupported number of channels: %d\n", s->channels);
932
-    s->chan_map = aac_chan_configs[s->channels-1];
930
+
931
+    s->needs_pce = 1;
932
+    for (i = 0; i < FF_ARRAY_ELEMS(aac_normal_chan_layouts); i++) {
933
+        if (avctx->channel_layout == aac_normal_chan_layouts[i]) {
934
+            s->needs_pce = s->options.pce;
935
+            break;
936
+        }
937
+    }
938
+
939
+    if (s->needs_pce) {
940
+        for (i = 0; i < FF_ARRAY_ELEMS(aac_pce_configs); i++)
941
+            if (avctx->channel_layout == aac_pce_configs[i].layout)
942
+                break;
943
+        ERROR_IF(i == FF_ARRAY_ELEMS(aac_pce_configs), "Unsupported channel layout\n");
944
+        av_log(avctx, AV_LOG_INFO, "Using a PCE to encode channel layout\n");
945
+        s->pce = aac_pce_configs[i];
946
+        s->reorder_map = s->pce.reorder_map;
947
+        s->chan_map = s->pce.config_map;
948
+    } else {
949
+        s->reorder_map = aac_chan_maps[s->channels - 1];
950
+        s->chan_map = aac_chan_configs[s->channels - 1];
951
+    }
952
+
933 953
     if (!avctx->bit_rate) {
934 954
         for (i = 1; i <= s->chan_map[0]; i++) {
935 955
             avctx->bit_rate += s->chan_map[i] == TYPE_CPE ? 128000 : /* Pair */
... ...
@@ -1062,6 +1118,7 @@ static const AVOption aacenc_options[] = {
1062 1062
     {"aac_tns", "Temporal noise shaping", offsetof(AACEncContext, options.tns), AV_OPT_TYPE_BOOL, {.i64 = 1}, -1, 1, AACENC_FLAGS},
1063 1063
     {"aac_ltp", "Long term prediction", offsetof(AACEncContext, options.ltp), AV_OPT_TYPE_BOOL, {.i64 = 0}, -1, 1, AACENC_FLAGS},
1064 1064
     {"aac_pred", "AAC-Main prediction", offsetof(AACEncContext, options.pred), AV_OPT_TYPE_BOOL, {.i64 = 0}, -1, 1, AACENC_FLAGS},
1065
+    {"aac_pce", "Forces the use of PCEs", offsetof(AACEncContext, options.pce), AV_OPT_TYPE_BOOL, {.i64 = 0}, -1, 1, AACENC_FLAGS},
1065 1066
     {NULL}
1066 1067
 };
1067 1068
 
... ...
@@ -45,6 +45,7 @@ typedef struct AACEncOptions {
45 45
     int pns;
46 46
     int tns;
47 47
     int ltp;
48
+    int pce;
48 49
     int pred;
49 50
     int mid_side;
50 51
     int intensity_stereo;
... ...
@@ -89,6 +90,286 @@ typedef struct AACQuantizeBandCostCacheEntry {
89 89
     uint16_t generation;
90 90
 } AACQuantizeBandCostCacheEntry;
91 91
 
92
+typedef struct AACPCEInfo {
93
+    int64_t layout;
94
+    int num_ele[4];                              ///< front, side, back, lfe
95
+    int pairing[3][8];                           ///< front, side, back
96
+    int index[4][8];                             ///< front, side, back, lfe
97
+    uint8_t config_map[16];                      ///< configs the encoder's channel specific settings
98
+    uint8_t reorder_map[16];                     ///< maps channels from lavc to aac order
99
+} AACPCEInfo;
100
+
101
+/**
102
+ * List of PCE (Program Configuration Element) for the channel layouts listed
103
+ * in channel_layout.h
104
+ *
105
+ * For those wishing in the future to add other layouts:
106
+ *
107
+ * - num_ele: number of elements in each group of front, side, back, lfe channels
108
+ *            (an element is of type SCE (single channel), CPE (channel pair) for
109
+ *            the first 3 groups; and is LFE for LFE group).
110
+ *
111
+ * - pairing: 0 for an SCE element or 1 for a CPE; does not apply to LFE group
112
+ *
113
+ * - index: there are three independent indices for SCE, CPE and LFE;
114
+ *     they are incremented irrespective of the group to which the element belongs;
115
+ *     they are not reset when going from one group to another
116
+ *
117
+ *     Example: for 7.0 channel layout,
118
+ *        .pairing = { { 1, 0 }, { 1 }, { 1 }, }, (3 CPE and 1 SCE in front group)
119
+ *        .index = { { 0, 0 }, { 1 }, { 2 }, },
120
+ *               (index is 0 for the single SCE but goes from 0 to 2 for the CPEs)
121
+ *
122
+ *     The index order impacts the channel ordering. But is otherwise arbitrary
123
+ *     (the sequence could have been 2, 0, 1 instead of 0, 1, 2).
124
+ *
125
+ *     Spec allows for discontinuous indices, e.g. if one has a total of two SCE,
126
+ *     SCE.0 SCE.15 is OK per spec; BUT it won't be decoded by our AAC decoder
127
+ *     which at this time requires that indices fully cover some range starting
128
+ *     from 0 (SCE.1 SCE.0 is OK but not SCE.0 SCE.15).
129
+ *
130
+ * - config_map: total number of elements and their types. Beware, the way the
131
+ *               types are ordered impacts the final channel ordering.
132
+ *
133
+ * - reorder_map: reorders the channels.
134
+ *
135
+ */
136
+static const AACPCEInfo aac_pce_configs[] = {
137
+    {
138
+        .layout = AV_CH_LAYOUT_MONO,
139
+        .num_ele = { 1, 0, 0, 0 },
140
+        .pairing = { { 0 }, },
141
+        .index = { { 0 }, },
142
+        .config_map = { 1, TYPE_SCE, },
143
+        .reorder_map = { 0 },
144
+    },
145
+    {
146
+        .layout = AV_CH_LAYOUT_STEREO,
147
+        .num_ele = { 1, 0, 0, 0 },
148
+        .pairing = { { 1 }, },
149
+        .index = { { 0 }, },
150
+        .config_map = { 1, TYPE_CPE, },
151
+        .reorder_map = { 0, 1 },
152
+    },
153
+    {
154
+        .layout = AV_CH_LAYOUT_2POINT1,
155
+        .num_ele = { 1, 0, 0, 1 },
156
+        .pairing = { { 1 }, },
157
+        .index = { { 0 },{ 0 },{ 0 },{ 0 } },
158
+        .config_map = { 2, TYPE_CPE, TYPE_LFE },
159
+        .reorder_map = { 0, 1, 2 },
160
+    },
161
+    {
162
+        .layout = AV_CH_LAYOUT_2_1,
163
+        .num_ele = { 1, 0, 1, 0 },
164
+        .pairing = { { 1 },{ 0 },{ 0 } },
165
+        .index = { { 0 },{ 0 },{ 0 }, },
166
+        .config_map = { 2, TYPE_CPE, TYPE_SCE },
167
+        .reorder_map = { 0, 1, 2 },
168
+    },
169
+    {
170
+        .layout = AV_CH_LAYOUT_SURROUND,
171
+        .num_ele = { 2, 0, 0, 0 },
172
+        .pairing = { { 1, 0 }, },
173
+        .index = { { 0, 0 }, },
174
+        .config_map = { 2, TYPE_CPE, TYPE_SCE, },
175
+        .reorder_map = { 0, 1, 2 },
176
+    },
177
+    {
178
+        .layout = AV_CH_LAYOUT_3POINT1,
179
+        .num_ele = { 2, 0, 0, 1 },
180
+        .pairing = { { 1, 0 }, },
181
+        .index = { { 0, 0 }, { 0 }, { 0 }, { 0 }, },
182
+        .config_map = { 3, TYPE_CPE, TYPE_SCE, TYPE_LFE },
183
+        .reorder_map = { 0, 1, 2, 3 },
184
+    },
185
+    {
186
+        .layout = AV_CH_LAYOUT_4POINT0,
187
+        .num_ele = { 2, 0, 1, 0 },
188
+        .pairing = { { 1, 0 }, { 0 }, { 0 }, },
189
+        .index = { { 0, 0 }, { 0 }, { 1 } },
190
+        .config_map = { 3, TYPE_CPE, TYPE_SCE, TYPE_SCE },
191
+        .reorder_map = {  0, 1, 2, 3 },
192
+    },
193
+    {
194
+        .layout = AV_CH_LAYOUT_4POINT1,
195
+        .num_ele = { 2, 1, 1, 0 },
196
+        .pairing = { { 1, 0 }, { 0 }, { 0 }, },
197
+        .index = { { 0, 0 }, { 1 }, { 2 }, { 0 } },
198
+        .config_map = { 4, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_SCE },
199
+        .reorder_map = { 0, 1, 2, 3, 4 },
200
+    },
201
+    {
202
+        .layout = AV_CH_LAYOUT_2_2,
203
+        .num_ele = { 1, 1, 0, 0 },
204
+        .pairing = { { 1 }, { 1 }, },
205
+        .index = { { 0 }, { 1 }, },
206
+        .config_map = { 2, TYPE_CPE, TYPE_CPE },
207
+        .reorder_map = { 0, 1, 2, 3 },
208
+    },
209
+    {
210
+        .layout = AV_CH_LAYOUT_QUAD,
211
+        .num_ele = { 1, 0, 1, 0 },
212
+        .pairing = { { 1 }, { 0 }, { 1 }, },
213
+        .index = { { 0 }, { 0 }, { 1 } },
214
+        .config_map = { 2, TYPE_CPE, TYPE_CPE },
215
+        .reorder_map = { 0, 1, 2, 3 },
216
+    },
217
+    {
218
+        .layout = AV_CH_LAYOUT_5POINT0,
219
+        .num_ele = { 2, 1, 0, 0 },
220
+        .pairing = { { 1, 0 }, { 1 }, },
221
+        .index = { { 0, 0 }, { 1 } },
222
+        .config_map = { 3, TYPE_CPE, TYPE_SCE, TYPE_CPE },
223
+        .reorder_map = { 0, 1, 2, 3, 4 },
224
+    },
225
+    {
226
+        .layout = AV_CH_LAYOUT_5POINT1,
227
+        .num_ele = { 2, 1, 1, 0 },
228
+        .pairing = { { 1, 0 }, { 0 }, { 1 }, },
229
+        .index = { { 0, 0 }, { 1 }, { 1 } },
230
+        .config_map = { 4, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_CPE },
231
+        .reorder_map = { 0, 1, 2, 3, 4, 5 },
232
+    },
233
+    {
234
+        .layout = AV_CH_LAYOUT_5POINT0_BACK,
235
+        .num_ele = { 2, 0, 1, 0 },
236
+        .pairing = { { 1, 0 }, { 0 }, { 1 } },
237
+        .index = { { 0, 0 }, { 0 }, { 1 } },
238
+        .config_map = { 3, TYPE_CPE, TYPE_SCE, TYPE_CPE },
239
+        .reorder_map = { 0, 1, 2, 3, 4 },
240
+    },
241
+    {
242
+        .layout = AV_CH_LAYOUT_5POINT1_BACK,
243
+        .num_ele = { 2, 1, 1, 0 },
244
+        .pairing = { { 1, 0 }, { 0 }, { 1 }, },
245
+        .index = { { 0, 0 }, { 1 }, { 1 } },
246
+        .config_map = { 4, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_CPE },
247
+        .reorder_map = { 0, 1, 2, 3, 4, 5 },
248
+    },
249
+    {
250
+        .layout = AV_CH_LAYOUT_6POINT0,
251
+        .num_ele = { 2, 1, 1, 0 },
252
+        .pairing = { { 1, 0 }, { 1 }, { 0 }, },
253
+        .index = { { 0, 0 }, { 1 }, { 1 } },
254
+        .config_map = { 4, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_SCE },
255
+        .reorder_map = { 0, 1, 2, 3, 4, 5 },
256
+    },
257
+    {
258
+        .layout = AV_CH_LAYOUT_6POINT0_FRONT,
259
+        .num_ele = { 2, 1, 0, 0 },
260
+        .pairing = { { 1, 1 }, { 1 } },
261
+        .index = { { 1, 0 }, { 2 }, },
262
+        .config_map = { 3, TYPE_CPE, TYPE_CPE, TYPE_CPE, },
263
+        .reorder_map = { 0, 1, 2, 3, 4, 5 },
264
+    },
265
+    {
266
+        .layout = AV_CH_LAYOUT_HEXAGONAL,
267
+        .num_ele = { 2, 0, 2, 0 },
268
+        .pairing = { { 1, 0 },{ 0 },{ 1, 0 }, },
269
+        .index = { { 0, 0 },{ 0 },{ 1, 1 } },
270
+        .config_map = { 4, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_SCE, },
271
+        .reorder_map = { 0, 1, 2, 3, 4, 5 },
272
+    },
273
+    {
274
+        .layout = AV_CH_LAYOUT_6POINT1,
275
+        .num_ele = { 2, 1, 2, 0 },
276
+        .pairing = { { 1, 0 },{ 0 },{ 1, 0 }, },
277
+        .index = { { 0, 0 },{ 1 },{ 1, 2 } },
278
+        .config_map = { 5, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_CPE, TYPE_SCE },
279
+        .reorder_map = { 0, 1, 2, 3, 4, 5, 6 },
280
+    },
281
+    {
282
+        .layout = AV_CH_LAYOUT_6POINT1_BACK,
283
+        .num_ele = { 2, 1, 2, 0 },
284
+        .pairing = { { 1, 0 }, { 0 }, { 1, 0 }, },
285
+        .index = { { 0, 0 }, { 1 }, { 1, 2 } },
286
+        .config_map = { 5, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_CPE, TYPE_SCE },
287
+        .reorder_map = { 0, 1, 2, 3, 4, 5, 6 },
288
+    },
289
+    {
290
+        .layout = AV_CH_LAYOUT_6POINT1_FRONT,
291
+        .num_ele = { 2, 1, 2, 0 },
292
+        .pairing = { { 1, 0 }, { 0 }, { 1, 0 }, },
293
+        .index = { { 0, 0 }, { 1 }, { 1, 2 } },
294
+        .config_map = { 5, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_CPE, TYPE_SCE },
295
+        .reorder_map = { 0, 1, 2, 3, 4, 5, 6 },
296
+    },
297
+    {
298
+        .layout = AV_CH_LAYOUT_7POINT0,
299
+        .num_ele = { 2, 1, 1, 0 },
300
+        .pairing = { { 1, 0 }, { 1 }, { 1 }, },
301
+        .index = { { 0, 0 }, { 1 }, { 2 }, },
302
+        .config_map = { 4, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_CPE },
303
+        .reorder_map = { 0, 1, 2, 3, 4, 5, 6 },
304
+    },
305
+    {
306
+        .layout = AV_CH_LAYOUT_7POINT0_FRONT,
307
+        .num_ele = { 2, 1, 1, 0 },
308
+        .pairing = { { 1, 0 }, { 1 }, { 1 }, },
309
+        .index = { { 0, 0 }, { 1 }, { 2 }, },
310
+        .config_map = { 4, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_CPE },
311
+        .reorder_map = { 0, 1, 2, 3, 4, 5, 6 },
312
+    },
313
+    {
314
+        .layout = AV_CH_LAYOUT_7POINT1,
315
+        .num_ele = { 2, 1, 2, 0 },
316
+        .pairing = { { 1, 0 }, { 0 }, { 1, 1 }, },
317
+        .index = { { 0, 0 }, { 1 }, { 1, 2 }, { 0 } },
318
+        .config_map = { 5, TYPE_CPE, TYPE_SCE,  TYPE_SCE, TYPE_CPE, TYPE_CPE },
319
+        .reorder_map = { 0, 1, 2, 3, 4, 5, 6, 7 },
320
+    },
321
+    {
322
+        .layout = AV_CH_LAYOUT_7POINT1_WIDE,
323
+        .num_ele = { 2, 1, 2, 0 },
324
+        .pairing = { { 1, 0 }, { 0 },{  1, 1 }, },
325
+        .index = { { 0, 0 }, { 1 }, { 1, 2 }, { 0 } },
326
+        .config_map = { 5, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_CPE, TYPE_CPE },
327
+        .reorder_map = { 0, 1, 2, 3, 4, 5, 6, 7 },
328
+    },
329
+    {
330
+        .layout = AV_CH_LAYOUT_7POINT1_WIDE_BACK,
331
+        .num_ele = { 2, 1, 2, 0 },
332
+        .pairing = { { 1, 0 }, { 0 }, { 1, 1 }, },
333
+        .index = { { 0, 0 }, { 1 }, { 1, 2 }, { 0 } },
334
+        .config_map = { 5, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_CPE, TYPE_CPE },
335
+        .reorder_map = { 0, 1, 2, 3, 4, 5, 6, 7 },
336
+    },
337
+    {
338
+        .layout = AV_CH_LAYOUT_OCTAGONAL,
339
+        .num_ele = { 2, 1, 2, 0 },
340
+        .pairing = { { 1, 0 }, { 1 }, { 1, 0 }, },
341
+        .index = { { 0, 0 }, { 1 }, { 2, 1 } },
342
+        .config_map = { 5, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_CPE, TYPE_SCE },
343
+        .reorder_map = { 0, 1, 2, 3, 4, 5, 6, 7 },
344
+    },
345
+    {   /* Meant for order 2/mixed ambisonics */
346
+        .layout = AV_CH_LAYOUT_OCTAGONAL | AV_CH_TOP_CENTER,
347
+        .num_ele = { 2, 2, 2, 0 },
348
+        .pairing = { { 1, 0 }, { 1, 0 }, { 1, 0 }, },
349
+        .index = { { 0, 0 }, { 1, 1 }, { 2, 2 } },
350
+        .config_map = { 6, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_SCE },
351
+        .reorder_map = { 0, 1, 2, 3, 4, 5, 6, 7, 8 },
352
+    },
353
+    {   /* Meant for order 2/mixed ambisonics */
354
+        .layout = AV_CH_LAYOUT_6POINT0_FRONT | AV_CH_BACK_CENTER |
355
+                  AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT | AV_CH_TOP_CENTER,
356
+        .num_ele = { 2, 2, 2, 0 },
357
+        .pairing = { { 1, 1 }, { 1, 0 }, { 1, 0 }, },
358
+        .index = { { 0, 1 }, { 2, 0 }, { 3, 1 } },
359
+        .config_map = { 6, TYPE_CPE, TYPE_CPE, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_SCE },
360
+        .reorder_map = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
361
+    },
362
+    {
363
+        .layout = AV_CH_LAYOUT_HEXADECAGONAL,
364
+        .num_ele = { 4, 2, 4, 0 },
365
+        .pairing = { { 1, 0, 1, 0 }, { 1, 1 }, { 1, 0, 1, 0 }, },
366
+        .index = { { 0, 0, 1, 1 }, { 2, 3 }, { 4, 2, 5, 3 } },
367
+        .config_map = { 10, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_CPE, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_SCE },
368
+        .reorder_map = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
369
+    },
370
+};
371
+
92 372
 /**
93 373
  * AAC encoder context
94 374
  */
... ...
@@ -99,12 +380,15 @@ typedef struct AACEncContext {
99 99
     FFTContext mdct1024;                         ///< long (1024 samples) frame transform context
100 100
     FFTContext mdct128;                          ///< short (128 samples) frame transform context
101 101
     AVFloatDSPContext *fdsp;
102
-    float *planar_samples[8];                    ///< saved preprocessed input
102
+    AACPCEInfo pce;                              ///< PCE data, if needed
103
+    float *planar_samples[16];                   ///< saved preprocessed input
103 104
 
104 105
     int profile;                                 ///< copied from avctx
106
+    int needs_pce;                               ///< flag for non-standard layout
105 107
     LPCContext lpc;                              ///< used by TNS
106 108
     int samplerate_index;                        ///< MPEG-4 samplerate index
107 109
     int channels;                                ///< channel count
110
+    const uint8_t *reorder_map;                  ///< lavc to aac reorder map
108 111
     const uint8_t *chan_map;                     ///< channel configuration map
109 112
 
110 113
     ChannelElement *cpe;                         ///< channel elements
... ...
@@ -36,13 +36,24 @@
36 36
 /** Total number of codebooks, including special ones **/
37 37
 #define CB_TOT_ALL 15
38 38
 
39
-#define AAC_MAX_CHANNELS 8
39
+#define AAC_MAX_CHANNELS 16
40 40
 
41 41
 extern const uint8_t *ff_aac_swb_size_1024[];
42 42
 extern const int      ff_aac_swb_size_1024_len;
43 43
 extern const uint8_t *ff_aac_swb_size_128[];
44 44
 extern const int      ff_aac_swb_size_128_len;
45 45
 
46
+/* Supported layouts without using a PCE */
47
+static const int64_t aac_normal_chan_layouts[7] = {
48
+    AV_CH_LAYOUT_MONO,
49
+    AV_CH_LAYOUT_STEREO,
50
+    AV_CH_LAYOUT_SURROUND,
51
+    AV_CH_LAYOUT_4POINT0,
52
+    AV_CH_LAYOUT_5POINT0,
53
+    AV_CH_LAYOUT_5POINT1,
54
+    AV_CH_LAYOUT_7POINT1,
55
+};
56
+
46 57
 /** default channel configurations */
47 58
 static const uint8_t aac_chan_configs[AAC_MAX_CHANNELS][6] = {
48 59
     {1, TYPE_SCE},                                         // 1 channel  - single channel element