/src/aac/libMpegTPEnc/src/tpenc_asc.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* ----------------------------------------------------------------------------- |
2 | | Software License for The Fraunhofer FDK AAC Codec Library for Android |
3 | | |
4 | | © Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten |
5 | | Forschung e.V. All rights reserved. |
6 | | |
7 | | 1. INTRODUCTION |
8 | | The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software |
9 | | that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding |
10 | | scheme for digital audio. This FDK AAC Codec software is intended to be used on |
11 | | a wide variety of Android devices. |
12 | | |
13 | | AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient |
14 | | general perceptual audio codecs. AAC-ELD is considered the best-performing |
15 | | full-bandwidth communications codec by independent studies and is widely |
16 | | deployed. AAC has been standardized by ISO and IEC as part of the MPEG |
17 | | specifications. |
18 | | |
19 | | Patent licenses for necessary patent claims for the FDK AAC Codec (including |
20 | | those of Fraunhofer) may be obtained through Via Licensing |
21 | | (www.vialicensing.com) or through the respective patent owners individually for |
22 | | the purpose of encoding or decoding bit streams in products that are compliant |
23 | | with the ISO/IEC MPEG audio standards. Please note that most manufacturers of |
24 | | Android devices already license these patent claims through Via Licensing or |
25 | | directly from the patent owners, and therefore FDK AAC Codec software may |
26 | | already be covered under those patent licenses when it is used for those |
27 | | licensed purposes only. |
28 | | |
29 | | Commercially-licensed AAC software libraries, including floating-point versions |
30 | | with enhanced sound quality, are also available from Fraunhofer. Users are |
31 | | encouraged to check the Fraunhofer website for additional applications |
32 | | information and documentation. |
33 | | |
34 | | 2. COPYRIGHT LICENSE |
35 | | |
36 | | Redistribution and use in source and binary forms, with or without modification, |
37 | | are permitted without payment of copyright license fees provided that you |
38 | | satisfy the following conditions: |
39 | | |
40 | | You must retain the complete text of this software license in redistributions of |
41 | | the FDK AAC Codec or your modifications thereto in source code form. |
42 | | |
43 | | You must retain the complete text of this software license in the documentation |
44 | | and/or other materials provided with redistributions of the FDK AAC Codec or |
45 | | your modifications thereto in binary form. You must make available free of |
46 | | charge copies of the complete source code of the FDK AAC Codec and your |
47 | | modifications thereto to recipients of copies in binary form. |
48 | | |
49 | | The name of Fraunhofer may not be used to endorse or promote products derived |
50 | | from this library without prior written permission. |
51 | | |
52 | | You may not charge copyright license fees for anyone to use, copy or distribute |
53 | | the FDK AAC Codec software or your modifications thereto. |
54 | | |
55 | | Your modified versions of the FDK AAC Codec must carry prominent notices stating |
56 | | that you changed the software and the date of any change. For modified versions |
57 | | of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" |
58 | | must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK |
59 | | AAC Codec Library for Android." |
60 | | |
61 | | 3. NO PATENT LICENSE |
62 | | |
63 | | NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without |
64 | | limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. |
65 | | Fraunhofer provides no warranty of patent non-infringement with respect to this |
66 | | software. |
67 | | |
68 | | You may use this FDK AAC Codec software or modifications thereto only for |
69 | | purposes that are authorized by appropriate patent licenses. |
70 | | |
71 | | 4. DISCLAIMER |
72 | | |
73 | | This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright |
74 | | holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, |
75 | | including but not limited to the implied warranties of merchantability and |
76 | | fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR |
77 | | CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, |
78 | | or consequential damages, including but not limited to procurement of substitute |
79 | | goods or services; loss of use, data, or profits, or business interruption, |
80 | | however caused and on any theory of liability, whether in contract, strict |
81 | | liability, or tort (including negligence), arising in any way out of the use of |
82 | | this software, even if advised of the possibility of such damage. |
83 | | |
84 | | 5. CONTACT INFORMATION |
85 | | |
86 | | Fraunhofer Institute for Integrated Circuits IIS |
87 | | Attention: Audio and Multimedia Departments - FDK AAC LL |
88 | | Am Wolfsmantel 33 |
89 | | 91058 Erlangen, Germany |
90 | | |
91 | | www.iis.fraunhofer.de/amm |
92 | | amm-info@iis.fraunhofer.de |
93 | | ----------------------------------------------------------------------------- */ |
94 | | |
95 | | /******************* MPEG transport format encoder library ********************* |
96 | | |
97 | | Author(s): |
98 | | |
99 | | Description: |
100 | | |
101 | | *******************************************************************************/ |
102 | | |
103 | | #include "tp_data.h" |
104 | | |
105 | | #include "tpenc_lib.h" |
106 | | #include "tpenc_asc.h" |
107 | | #include "FDK_bitstream.h" |
108 | | #include "genericStds.h" |
109 | | |
110 | | #include "FDK_crc.h" |
111 | | |
112 | 0 | #define PCE_HEIGHT_EXT_SYNC (0xAC) |
113 | 0 | #define HEIGHT_NORMAL 0 |
114 | 0 | #define HEIGHT_TOP 1 |
115 | 0 | #define HEIGHT_BOTTOM 2 |
116 | | #define MAX_FRONT_ELEMENTS 8 |
117 | | #define MAX_SIDE_ELEMENTS 3 |
118 | | #define MAX_BACK_ELEMENTS 4 |
119 | | |
120 | | /** |
121 | | * Describe additional PCE height information for front, side and back channel |
122 | | * elements. |
123 | | */ |
124 | | typedef struct { |
125 | | UCHAR |
126 | | num_front_height_channel_elements[2]; /*!< Number of front channel |
127 | | elements in top [0] and bottom |
128 | | [1] plane. */ |
129 | | UCHAR num_side_height_channel_elements[2]; /*!< Number of side channel |
130 | | elements in top [0] and bottom |
131 | | [1] plane. */ |
132 | | UCHAR num_back_height_channel_elements[2]; /*!< Number of back channel |
133 | | elements in top [0] and bottom |
134 | | [1] plane. */ |
135 | | } PCE_HEIGHT_NUM; |
136 | | |
137 | | /** |
138 | | * Describe a PCE based on placed channel elements and element type sequence. |
139 | | */ |
140 | | typedef struct { |
141 | | UCHAR num_front_channel_elements; /*!< Number of front channel elements. */ |
142 | | UCHAR num_side_channel_elements; /*!< Number of side channel elements. */ |
143 | | UCHAR num_back_channel_elements; /*!< Number of back channel elements. */ |
144 | | UCHAR num_lfe_channel_elements; /*!< Number of lfe channel elements. */ |
145 | | const MP4_ELEMENT_ID |
146 | | *pEl_type; /*!< List contains sequence describing the elements |
147 | | in present channel mode. (MPEG order) */ |
148 | | const PCE_HEIGHT_NUM *pHeight_num; |
149 | | } PCE_CONFIGURATION; |
150 | | |
151 | | /** |
152 | | * Map an incoming channel mode to a existing PCE configuration entry. |
153 | | */ |
154 | | typedef struct { |
155 | | CHANNEL_MODE channel_mode; /*!< Present channel mode. */ |
156 | | PCE_CONFIGURATION |
157 | | pce_configuration; /*!< Program config element description. */ |
158 | | |
159 | | } CHANNEL_CONFIGURATION; |
160 | | |
161 | | /** |
162 | | * The following arrays provide the IDs of the consecutive elements for each |
163 | | * mode. |
164 | | */ |
165 | | static const MP4_ELEMENT_ID elType_1[] = {ID_SCE}; |
166 | | static const MP4_ELEMENT_ID elType_2[] = {ID_CPE}; |
167 | | static const MP4_ELEMENT_ID elType_1_2[] = {ID_SCE, ID_CPE}; |
168 | | static const MP4_ELEMENT_ID elType_1_2_1[] = {ID_SCE, ID_CPE, ID_SCE}; |
169 | | static const MP4_ELEMENT_ID elType_1_2_2[] = {ID_SCE, ID_CPE, ID_CPE}; |
170 | | static const MP4_ELEMENT_ID elType_1_2_2_1[] = {ID_SCE, ID_CPE, ID_CPE, ID_LFE}; |
171 | | static const MP4_ELEMENT_ID elType_1_2_2_2_1[] = {ID_SCE, ID_CPE, ID_CPE, |
172 | | ID_CPE, ID_LFE}; |
173 | | static const MP4_ELEMENT_ID elType_6_1[] = {ID_SCE, ID_CPE, ID_CPE, ID_SCE, |
174 | | ID_LFE}; |
175 | | static const MP4_ELEMENT_ID elType_7_1_back[] = {ID_SCE, ID_CPE, ID_CPE, ID_CPE, |
176 | | ID_LFE}; |
177 | | static const MP4_ELEMENT_ID elType_7_1_top_front[] = {ID_SCE, ID_CPE, ID_CPE, |
178 | | ID_LFE, ID_CPE}; |
179 | | static const MP4_ELEMENT_ID elType_7_1_rear_surround[] = { |
180 | | ID_SCE, ID_CPE, ID_CPE, ID_CPE, ID_LFE}; |
181 | | static const MP4_ELEMENT_ID elType_7_1_front_center[] = {ID_SCE, ID_CPE, ID_CPE, |
182 | | ID_CPE, ID_LFE}; |
183 | | |
184 | | /** |
185 | | * The following arrays provide information on how many front, side and back |
186 | | * elements are assigned to the top or bottom plane for each mode that comprises |
187 | | * height information. |
188 | | */ |
189 | | static const PCE_HEIGHT_NUM heightNum_7_1_top_front = {{1, 0}, {0, 0}, {0, 0}}; |
190 | | |
191 | | /** |
192 | | * \brief Table contains all supported channel modes and according PCE |
193 | | configuration description. |
194 | | * |
195 | | * The mode identifier is followed by the number of front, side, back, and LFE |
196 | | elements. |
197 | | * These are followed by a pointer to the IDs of the consecutive elements |
198 | | (ID_SCE, ID_CPE, ID_LFE). |
199 | | * |
200 | | * For some modes (MODE_7_1_TOP_FRONT and MODE_22_2) additional height |
201 | | information is transmitted. |
202 | | * In this case the additional pointer provides information on how many front, |
203 | | side and back elements |
204 | | * are assigned to the top or bottom plane.The elements are arranged in the |
205 | | following order: normal height (front, side, back, LFE), top height (front, |
206 | | side, back), bottom height (front, side, back). |
207 | | * |
208 | | * |
209 | | * E.g. MODE_7_1_TOP_FRONT means: |
210 | | * - 3 elements are front channel elements. |
211 | | * - 0 elements are side channel elements. |
212 | | * - 1 element is back channel element. |
213 | | * - 1 element is an LFE channel element. |
214 | | * - the element order is ID_SCE, ID_CPE, ID_CPE, |
215 | | ID_LFE, ID_CPE. |
216 | | * - 1 of the front elements is in the top plane. |
217 | | * |
218 | | * This leads to the following mapping for the cconsecutive elements in the |
219 | | MODE_7_1_TOP_FRONT bitstream: |
220 | | * - ID_SCE -> normal height front, |
221 | | - ID_CPE -> normal height front, |
222 | | - ID_CPE -> normal height back, |
223 | | - ID_LFE -> normal height LFE, |
224 | | - ID_CPE -> top height front. |
225 | | */ |
226 | | static const CHANNEL_CONFIGURATION pceConfigTab[] = { |
227 | | {MODE_1, |
228 | | {1, 0, 0, 0, elType_1, |
229 | | NULL}}, /* don't transmit height information in this mode */ |
230 | | {MODE_2, |
231 | | {1, 0, 0, 0, elType_2, |
232 | | NULL}}, /* don't transmit height information in this mode */ |
233 | | {MODE_1_2, |
234 | | {2, 0, 0, 0, elType_1_2, |
235 | | NULL}}, /* don't transmit height information in this mode */ |
236 | | {MODE_1_2_1, |
237 | | {2, 0, 1, 0, elType_1_2_1, |
238 | | NULL}}, /* don't transmit height information in this mode */ |
239 | | {MODE_1_2_2, |
240 | | {2, 0, 1, 0, elType_1_2_2, |
241 | | NULL}}, /* don't transmit height information in this mode */ |
242 | | {MODE_1_2_2_1, |
243 | | {2, 0, 1, 1, elType_1_2_2_1, |
244 | | NULL}}, /* don't transmit height information in this mode */ |
245 | | {MODE_1_2_2_2_1, |
246 | | {3, 0, 1, 1, elType_1_2_2_2_1, |
247 | | NULL}}, /* don't transmit height information in this mode */ |
248 | | |
249 | | {MODE_6_1, |
250 | | {2, 0, 2, 1, elType_6_1, |
251 | | NULL}}, /* don't transmit height information in this mode */ |
252 | | {MODE_7_1_BACK, |
253 | | {2, 0, 2, 1, elType_7_1_back, |
254 | | NULL}}, /* don't transmit height information in this mode */ |
255 | | {MODE_7_1_TOP_FRONT, |
256 | | {3, 0, 1, 1, elType_7_1_top_front, &heightNum_7_1_top_front}}, |
257 | | |
258 | | {MODE_7_1_REAR_SURROUND, |
259 | | {2, 0, 2, 1, elType_7_1_rear_surround, |
260 | | NULL}}, /* don't transmit height information in this mode */ |
261 | | {MODE_7_1_FRONT_CENTER, |
262 | | {3, 0, 1, 1, elType_7_1_front_center, |
263 | | NULL}} /* don't transmit height information in this mode */ |
264 | | }; |
265 | | |
266 | | /** |
267 | | * \brief Get program config element description for existing channel mode. |
268 | | * |
269 | | * \param channel_mode Current channel mode. |
270 | | * |
271 | | * \return |
272 | | * - Pointer to PCE_CONFIGURATION entry, on success. |
273 | | * - NULL, on failure. |
274 | | */ |
275 | 0 | static const PCE_CONFIGURATION *getPceEntry(const CHANNEL_MODE channel_mode) { |
276 | 0 | UINT i; |
277 | 0 | const PCE_CONFIGURATION *pce_config = NULL; |
278 | |
|
279 | 0 | for (i = 0; i < (sizeof(pceConfigTab) / sizeof(CHANNEL_CONFIGURATION)); i++) { |
280 | 0 | if (pceConfigTab[i].channel_mode == channel_mode) { |
281 | 0 | pce_config = &pceConfigTab[i].pce_configuration; |
282 | 0 | break; |
283 | 0 | } |
284 | 0 | } |
285 | |
|
286 | 0 | return pce_config; |
287 | 0 | } |
288 | | |
289 | | int getChannelConfig(const CHANNEL_MODE channel_mode, |
290 | 0 | const UCHAR channel_config_zero) { |
291 | 0 | INT chan_config = 0; |
292 | |
|
293 | 0 | if (channel_config_zero != 0) { |
294 | 0 | chan_config = 0; |
295 | 0 | } else { |
296 | 0 | switch (channel_mode) { |
297 | 0 | case MODE_1: |
298 | 0 | chan_config = 1; |
299 | 0 | break; |
300 | 0 | case MODE_2: |
301 | 0 | chan_config = 2; |
302 | 0 | break; |
303 | 0 | case MODE_1_2: |
304 | 0 | chan_config = 3; |
305 | 0 | break; |
306 | 0 | case MODE_1_2_1: |
307 | 0 | chan_config = 4; |
308 | 0 | break; |
309 | 0 | case MODE_1_2_2: |
310 | 0 | chan_config = 5; |
311 | 0 | break; |
312 | 0 | case MODE_1_2_2_1: |
313 | 0 | chan_config = 6; |
314 | 0 | break; |
315 | 0 | case MODE_1_2_2_2_1: |
316 | 0 | chan_config = 7; |
317 | 0 | break; |
318 | 0 | case MODE_6_1: |
319 | 0 | chan_config = 11; |
320 | 0 | break; |
321 | 0 | case MODE_7_1_BACK: |
322 | 0 | chan_config = 12; |
323 | 0 | break; |
324 | 0 | case MODE_7_1_TOP_FRONT: |
325 | 0 | chan_config = 14; |
326 | 0 | break; |
327 | 0 | default: |
328 | 0 | chan_config = 0; |
329 | 0 | } |
330 | 0 | } |
331 | | |
332 | 0 | return chan_config; |
333 | 0 | } |
334 | | |
335 | 0 | CHANNEL_MODE transportEnc_GetChannelMode(int noChannels) { |
336 | 0 | CHANNEL_MODE chMode; |
337 | |
|
338 | 0 | if (noChannels <= 8 && noChannels > 0) |
339 | 0 | chMode = (CHANNEL_MODE)( |
340 | 0 | (noChannels == 8) ? 7 |
341 | 0 | : noChannels); /* see : iso/mpeg4 v1 audio subpart1*/ |
342 | 0 | else |
343 | 0 | chMode = MODE_UNKNOWN; |
344 | |
|
345 | 0 | return chMode; |
346 | 0 | } |
347 | | |
348 | | int transportEnc_writePCE(HANDLE_FDK_BITSTREAM hBs, CHANNEL_MODE channelMode, |
349 | | INT sampleRate, int instanceTagPCE, int profile, |
350 | | int matrixMixdownA, int pseudoSurroundEnable, |
351 | 0 | UINT alignAnchor) { |
352 | 0 | int sampleRateIndex, i; |
353 | 0 | const PCE_CONFIGURATION *config = NULL; |
354 | 0 | const MP4_ELEMENT_ID *pEl_list = NULL; |
355 | 0 | UCHAR cpeCnt = 0, sceCnt = 0, lfeCnt = 0, frntCnt = 0, sdCnt = 0, bckCnt = 0, |
356 | 0 | isCpe = 0, tag = 0, normalFrontEnd = 0, normalSideEnd = 0, |
357 | 0 | normalBackEnd = 0, topFrontEnd = 0, topSideEnd = 0, topBackEnd = 0, |
358 | 0 | bottomFrontEnd = 0, bottomSideEnd = 0; |
359 | 0 | #ifdef FDK_ASSERT_ENABLE |
360 | 0 | UCHAR bottomBackEnd = 0; |
361 | 0 | #endif |
362 | 0 | enum elementDepth { FRONT, SIDE, BACK } elDepth; |
363 | |
|
364 | 0 | sampleRateIndex = getSamplingRateIndex(sampleRate, 4); |
365 | 0 | if (sampleRateIndex == 15) { |
366 | 0 | return -1; |
367 | 0 | } |
368 | | |
369 | 0 | if ((config = getPceEntry(channelMode)) == NULL) { |
370 | 0 | return -1; |
371 | 0 | } |
372 | | |
373 | 0 | FDK_ASSERT(config->num_front_channel_elements <= MAX_FRONT_ELEMENTS); |
374 | 0 | FDK_ASSERT(config->num_side_channel_elements <= MAX_SIDE_ELEMENTS); |
375 | 0 | FDK_ASSERT(config->num_back_channel_elements <= MAX_BACK_ELEMENTS); |
376 | | |
377 | 0 | UCHAR frontIsCpe[MAX_FRONT_ELEMENTS] = {0}, |
378 | 0 | frontTag[MAX_FRONT_ELEMENTS] = {0}, sideIsCpe[MAX_SIDE_ELEMENTS] = {0}, |
379 | 0 | sideTag[MAX_SIDE_ELEMENTS] = {0}, backIsCpe[MAX_BACK_ELEMENTS] = {0}, |
380 | 0 | backTag[MAX_BACK_ELEMENTS] = {0}; |
381 | | |
382 | | /* Write general information */ |
383 | |
|
384 | 0 | FDKwriteBits(hBs, instanceTagPCE, 4); /* Element instance tag */ |
385 | 0 | FDKwriteBits(hBs, profile, 2); /* Object type */ |
386 | 0 | FDKwriteBits(hBs, sampleRateIndex, 4); /* Sample rate index*/ |
387 | |
|
388 | 0 | FDKwriteBits(hBs, config->num_front_channel_elements, |
389 | 0 | 4); /* Front channel Elements */ |
390 | 0 | FDKwriteBits(hBs, config->num_side_channel_elements, |
391 | 0 | 4); /* No Side Channel Elements */ |
392 | 0 | FDKwriteBits(hBs, config->num_back_channel_elements, |
393 | 0 | 4); /* No Back channel Elements */ |
394 | 0 | FDKwriteBits(hBs, config->num_lfe_channel_elements, |
395 | 0 | 2); /* No Lfe channel elements */ |
396 | |
|
397 | 0 | FDKwriteBits(hBs, 0, 3); /* No assoc data elements */ |
398 | 0 | FDKwriteBits(hBs, 0, 4); /* No valid cc elements */ |
399 | 0 | FDKwriteBits(hBs, 0, 1); /* Mono mixdown present */ |
400 | 0 | FDKwriteBits(hBs, 0, 1); /* Stereo mixdown present */ |
401 | |
|
402 | 0 | if (matrixMixdownA != 0 && |
403 | 0 | ((channelMode == MODE_1_2_2) || (channelMode == MODE_1_2_2_1))) { |
404 | 0 | FDKwriteBits(hBs, 1, 1); /* Matrix mixdown present */ |
405 | 0 | FDKwriteBits(hBs, (matrixMixdownA - 1) & 0x3, 2); /* matrix_mixdown_idx */ |
406 | 0 | FDKwriteBits(hBs, (pseudoSurroundEnable) ? 1 : 0, |
407 | 0 | 1); /* pseudo_surround_enable */ |
408 | 0 | } else { |
409 | 0 | FDKwriteBits(hBs, 0, 1); /* Matrix mixdown not present */ |
410 | 0 | } |
411 | |
|
412 | 0 | if (config->pHeight_num != NULL) { |
413 | | /* we have up to three different height levels, and in each height level we |
414 | | * may have front, side and back channels. We need to know where each |
415 | | * section ends to correctly count the tags */ |
416 | 0 | normalFrontEnd = config->num_front_channel_elements - |
417 | 0 | config->pHeight_num->num_front_height_channel_elements[0] - |
418 | 0 | config->pHeight_num->num_front_height_channel_elements[1]; |
419 | 0 | normalSideEnd = normalFrontEnd + config->num_side_channel_elements - |
420 | 0 | config->pHeight_num->num_side_height_channel_elements[0] - |
421 | 0 | config->pHeight_num->num_side_height_channel_elements[1]; |
422 | 0 | normalBackEnd = normalSideEnd + config->num_back_channel_elements - |
423 | 0 | config->pHeight_num->num_back_height_channel_elements[0] - |
424 | 0 | config->pHeight_num->num_back_height_channel_elements[1]; |
425 | |
|
426 | 0 | topFrontEnd = |
427 | 0 | normalBackEnd + config->num_lfe_channel_elements + |
428 | 0 | config->pHeight_num->num_front_height_channel_elements[0]; /* only |
429 | | normal |
430 | | height |
431 | | LFEs |
432 | | assumed */ |
433 | 0 | topSideEnd = |
434 | 0 | topFrontEnd + config->pHeight_num->num_side_height_channel_elements[0]; |
435 | 0 | topBackEnd = |
436 | 0 | topSideEnd + config->pHeight_num->num_back_height_channel_elements[0]; |
437 | |
|
438 | 0 | bottomFrontEnd = |
439 | 0 | topBackEnd + config->pHeight_num->num_front_height_channel_elements[1]; |
440 | 0 | bottomSideEnd = bottomFrontEnd + |
441 | 0 | config->pHeight_num->num_side_height_channel_elements[1]; |
442 | 0 | #ifdef FDK_ASSERT_ENABLE |
443 | 0 | bottomBackEnd = bottomSideEnd + |
444 | 0 | config->pHeight_num->num_back_height_channel_elements[1]; |
445 | 0 | #endif |
446 | |
|
447 | 0 | } else { |
448 | | /* we have only one height level, so we don't care about top or bottom */ |
449 | 0 | normalFrontEnd = config->num_front_channel_elements; |
450 | 0 | normalSideEnd = normalFrontEnd + config->num_side_channel_elements; |
451 | 0 | normalBackEnd = normalSideEnd + config->num_back_channel_elements; |
452 | 0 | } |
453 | | |
454 | | /* assign cpe and tag information to either front, side or back channels */ |
455 | |
|
456 | 0 | pEl_list = config->pEl_type; |
457 | |
|
458 | 0 | for (i = 0; i < config->num_front_channel_elements + |
459 | 0 | config->num_side_channel_elements + |
460 | 0 | config->num_back_channel_elements + |
461 | 0 | config->num_lfe_channel_elements; |
462 | 0 | i++) { |
463 | 0 | if (*pEl_list == ID_LFE) { |
464 | 0 | pEl_list++; |
465 | 0 | continue; |
466 | 0 | } |
467 | 0 | isCpe = (*pEl_list++ == ID_CPE) ? 1 : 0; |
468 | 0 | tag = (isCpe) ? cpeCnt++ : sceCnt++; |
469 | |
|
470 | 0 | if (i < normalFrontEnd) |
471 | 0 | elDepth = FRONT; |
472 | 0 | else if (i < normalSideEnd) |
473 | 0 | elDepth = SIDE; |
474 | 0 | else if (i < normalBackEnd) |
475 | 0 | elDepth = BACK; |
476 | 0 | else if (i < topFrontEnd) |
477 | 0 | elDepth = FRONT; |
478 | 0 | else if (i < topSideEnd) |
479 | 0 | elDepth = SIDE; |
480 | 0 | else if (i < topBackEnd) |
481 | 0 | elDepth = BACK; |
482 | 0 | else if (i < bottomFrontEnd) |
483 | 0 | elDepth = FRONT; |
484 | 0 | else if (i < bottomSideEnd) |
485 | 0 | elDepth = SIDE; |
486 | 0 | else { |
487 | 0 | elDepth = BACK; |
488 | 0 | FDK_ASSERT(i < bottomBackEnd); /* won't fail if implementation of pce |
489 | | configuration table is correct */ |
490 | 0 | } |
491 | | |
492 | 0 | switch (elDepth) { |
493 | 0 | case FRONT: |
494 | 0 | FDK_ASSERT(frntCnt < config->num_front_channel_elements); |
495 | 0 | frontIsCpe[frntCnt] = isCpe; |
496 | 0 | frontTag[frntCnt++] = tag; |
497 | 0 | break; |
498 | 0 | case SIDE: |
499 | 0 | FDK_ASSERT(sdCnt < config->num_side_channel_elements); |
500 | 0 | sideIsCpe[sdCnt] = isCpe; |
501 | 0 | sideTag[sdCnt++] = tag; |
502 | 0 | break; |
503 | 0 | case BACK: |
504 | 0 | FDK_ASSERT(bckCnt < config->num_back_channel_elements); |
505 | 0 | backIsCpe[bckCnt] = isCpe; |
506 | 0 | backTag[bckCnt++] = tag; |
507 | 0 | break; |
508 | 0 | } |
509 | 0 | } |
510 | | |
511 | | /* Write front channel isCpe and tags */ |
512 | 0 | for (i = 0; i < config->num_front_channel_elements; i++) { |
513 | 0 | FDKwriteBits(hBs, frontIsCpe[i], 1); |
514 | 0 | FDKwriteBits(hBs, frontTag[i], 4); |
515 | 0 | } |
516 | | /* Write side channel isCpe and tags */ |
517 | 0 | for (i = 0; i < config->num_side_channel_elements; i++) { |
518 | 0 | FDKwriteBits(hBs, sideIsCpe[i], 1); |
519 | 0 | FDKwriteBits(hBs, sideTag[i], 4); |
520 | 0 | } |
521 | | /* Write back channel isCpe and tags */ |
522 | 0 | for (i = 0; i < config->num_back_channel_elements; i++) { |
523 | 0 | FDKwriteBits(hBs, backIsCpe[i], 1); |
524 | 0 | FDKwriteBits(hBs, backTag[i], 4); |
525 | 0 | } |
526 | | /* Write LFE information */ |
527 | 0 | for (i = 0; i < config->num_lfe_channel_elements; i++) { |
528 | 0 | FDKwriteBits(hBs, lfeCnt++, 4); /* LFE channel Instance Tag. */ |
529 | 0 | } |
530 | | |
531 | | /* - num_valid_cc_elements always 0. |
532 | | - num_assoc_data_elements always 0. */ |
533 | | |
534 | | /* Byte alignment: relative to alignAnchor |
535 | | ADTS: align with respect to the first bit of the raw_data_block() |
536 | | ADIF: align with respect to the first bit of the header |
537 | | LATM: align with respect to the first bit of the ASC */ |
538 | 0 | FDKbyteAlign(hBs, alignAnchor); /* Alignment */ |
539 | | |
540 | | /* Write comment information */ |
541 | |
|
542 | 0 | if (config->pHeight_num != NULL) { |
543 | | /* embed height information in comment field */ |
544 | |
|
545 | 0 | INT commentBytes = |
546 | 0 | 1 /* PCE_HEIGHT_EXT_SYNC */ |
547 | 0 | + ((((config->num_front_channel_elements + |
548 | 0 | config->num_side_channel_elements + |
549 | 0 | config->num_back_channel_elements) |
550 | 0 | << 1) + |
551 | 0 | 7) >> |
552 | 0 | 3) /* 2 bit height info per element, round up to full bytes */ |
553 | 0 | + 1; /* CRC */ |
554 | |
|
555 | 0 | FDKwriteBits(hBs, commentBytes, 8); /* comment size. */ |
556 | |
|
557 | 0 | FDK_CRCINFO crcInfo; /* CRC state info */ |
558 | 0 | INT crcReg; |
559 | |
|
560 | 0 | FDKcrcInit(&crcInfo, 0x07, 0xFF, 8); |
561 | 0 | crcReg = FDKcrcStartReg(&crcInfo, hBs, 0); |
562 | |
|
563 | 0 | FDKwriteBits(hBs, PCE_HEIGHT_EXT_SYNC, 8); /* indicate height extension */ |
564 | | |
565 | | /* front channel height information */ |
566 | 0 | for (i = 0; |
567 | 0 | i < config->num_front_channel_elements - |
568 | 0 | config->pHeight_num->num_front_height_channel_elements[0] - |
569 | 0 | config->pHeight_num->num_front_height_channel_elements[1]; |
570 | 0 | i++) |
571 | 0 | FDKwriteBits(hBs, HEIGHT_NORMAL, 2); |
572 | 0 | for (i = 0; i < config->pHeight_num->num_front_height_channel_elements[0]; |
573 | 0 | i++) |
574 | 0 | FDKwriteBits(hBs, HEIGHT_TOP, 2); |
575 | 0 | for (i = 0; i < config->pHeight_num->num_front_height_channel_elements[1]; |
576 | 0 | i++) |
577 | 0 | FDKwriteBits(hBs, HEIGHT_BOTTOM, 2); |
578 | | |
579 | | /* side channel height information */ |
580 | 0 | for (i = 0; |
581 | 0 | i < config->num_side_channel_elements - |
582 | 0 | config->pHeight_num->num_side_height_channel_elements[0] - |
583 | 0 | config->pHeight_num->num_side_height_channel_elements[1]; |
584 | 0 | i++) |
585 | 0 | FDKwriteBits(hBs, HEIGHT_NORMAL, 2); |
586 | 0 | for (i = 0; i < config->pHeight_num->num_side_height_channel_elements[0]; |
587 | 0 | i++) |
588 | 0 | FDKwriteBits(hBs, HEIGHT_TOP, 2); |
589 | 0 | for (i = 0; i < config->pHeight_num->num_side_height_channel_elements[1]; |
590 | 0 | i++) |
591 | 0 | FDKwriteBits(hBs, HEIGHT_BOTTOM, 2); |
592 | | |
593 | | /* back channel height information */ |
594 | 0 | for (i = 0; |
595 | 0 | i < config->num_back_channel_elements - |
596 | 0 | config->pHeight_num->num_back_height_channel_elements[0] - |
597 | 0 | config->pHeight_num->num_back_height_channel_elements[1]; |
598 | 0 | i++) |
599 | 0 | FDKwriteBits(hBs, HEIGHT_NORMAL, 2); |
600 | 0 | for (i = 0; i < config->pHeight_num->num_back_height_channel_elements[0]; |
601 | 0 | i++) |
602 | 0 | FDKwriteBits(hBs, HEIGHT_TOP, 2); |
603 | 0 | for (i = 0; i < config->pHeight_num->num_back_height_channel_elements[1]; |
604 | 0 | i++) |
605 | 0 | FDKwriteBits(hBs, HEIGHT_BOTTOM, 2); |
606 | |
|
607 | 0 | FDKbyteAlign(hBs, alignAnchor); /* Alignment */ |
608 | |
|
609 | 0 | FDKcrcEndReg(&crcInfo, hBs, crcReg); |
610 | 0 | FDKwriteBits(hBs, FDKcrcGetCRC(&crcInfo), 8); |
611 | |
|
612 | 0 | } else { |
613 | 0 | FDKwriteBits(hBs, 0, |
614 | 0 | 8); /* Do no write any comment or height information. */ |
615 | 0 | } |
616 | |
|
617 | 0 | return 0; |
618 | 0 | } |
619 | | |
620 | | int transportEnc_GetPCEBits(CHANNEL_MODE channelMode, int matrixMixdownA, |
621 | 0 | int bits) { |
622 | 0 | const PCE_CONFIGURATION *config = NULL; |
623 | |
|
624 | 0 | if ((config = getPceEntry(channelMode)) == NULL) { |
625 | 0 | return -1; /* unsupported channelmapping */ |
626 | 0 | } |
627 | | |
628 | 0 | bits += |
629 | 0 | 4 + 2 + 4; /* Element instance tag + Object type + Sample rate index */ |
630 | 0 | bits += 4 + 4 + 4 + 2; /* No (front + side + back + lfe channel) elements */ |
631 | 0 | bits += 3 + 4; /* No (assoc data + valid cc) elements */ |
632 | 0 | bits += 1 + 1 + 1; /* Mono + Stereo + Matrix mixdown present */ |
633 | |
|
634 | 0 | if (matrixMixdownA != 0 && |
635 | 0 | ((channelMode == MODE_1_2_2) || (channelMode == MODE_1_2_2_1))) { |
636 | 0 | bits += 3; /* matrix_mixdown_idx + pseudo_surround_enable */ |
637 | 0 | } |
638 | |
|
639 | 0 | bits += (1 + 4) * (INT)config->num_front_channel_elements; |
640 | 0 | bits += (1 + 4) * (INT)config->num_side_channel_elements; |
641 | 0 | bits += (1 + 4) * (INT)config->num_back_channel_elements; |
642 | 0 | bits += (4) * (INT)config->num_lfe_channel_elements; |
643 | | |
644 | | /* - num_valid_cc_elements always 0. |
645 | | - num_assoc_data_elements always 0. */ |
646 | |
|
647 | 0 | if ((bits % 8) != 0) { |
648 | 0 | bits += (8 - (bits % 8)); /* Alignment */ |
649 | 0 | } |
650 | |
|
651 | 0 | bits += 8; /* Comment field bytes */ |
652 | |
|
653 | 0 | if (config->pHeight_num != NULL) { |
654 | | /* Comment field (height extension) */ |
655 | |
|
656 | 0 | bits += |
657 | 0 | 8 /* PCE_HEIGHT_EXT_SYNC */ |
658 | 0 | + |
659 | 0 | ((config->num_front_channel_elements + |
660 | 0 | config->num_side_channel_elements + config->num_back_channel_elements) |
661 | 0 | << 1) /* 2 bit height info per element */ |
662 | 0 | + 8; /* CRC */ |
663 | |
|
664 | 0 | if ((bits % 8) != 0) { |
665 | 0 | bits += (8 - (bits % 8)); /* Alignment */ |
666 | 0 | } |
667 | 0 | } |
668 | |
|
669 | 0 | return bits; |
670 | 0 | } |
671 | | |
672 | | static void writeAot(HANDLE_FDK_BITSTREAM hBitstreamBuffer, |
673 | 0 | AUDIO_OBJECT_TYPE aot) { |
674 | 0 | int tmp = (int)aot; |
675 | |
|
676 | 0 | if (tmp > 31) { |
677 | 0 | FDKwriteBits(hBitstreamBuffer, AOT_ESCAPE, 5); |
678 | 0 | FDKwriteBits(hBitstreamBuffer, tmp - 32, 6); /* AudioObjectType */ |
679 | 0 | } else { |
680 | 0 | FDKwriteBits(hBitstreamBuffer, tmp, 5); |
681 | 0 | } |
682 | 0 | } |
683 | | |
684 | | static void writeSampleRate(HANDLE_FDK_BITSTREAM hBs, int sampleRate, |
685 | 0 | int nBits) { |
686 | 0 | int srIdx = getSamplingRateIndex(sampleRate, nBits); |
687 | |
|
688 | 0 | FDKwriteBits(hBs, srIdx, nBits); |
689 | 0 | if (srIdx == (1 << nBits) - 1) { |
690 | 0 | FDKwriteBits(hBs, sampleRate, 24); |
691 | 0 | } |
692 | 0 | } |
693 | | |
694 | | static int transportEnc_writeGASpecificConfig(HANDLE_FDK_BITSTREAM asc, |
695 | | CODER_CONFIG *config, int extFlg, |
696 | 0 | UINT alignAnchor) { |
697 | 0 | int aot = config->aot; |
698 | 0 | int samplesPerFrame = config->samplesPerFrame; |
699 | | |
700 | | /* start of GASpecificConfig according to ISO/IEC 14496-3 Subpart 4, 4.4.1 */ |
701 | 0 | FDKwriteBits(asc, |
702 | 0 | ((samplesPerFrame == 960 || samplesPerFrame == 480) ? 1 : 0), |
703 | 0 | 1); /* frameLengthFlag: 1 for a 960/480 (I)MDCT, 0 for a 1024/512 |
704 | | (I)MDCT*/ |
705 | 0 | FDKwriteBits(asc, 0, |
706 | 0 | 1); /* dependsOnCoreCoder: Sampling Rate Coder Specific, see in |
707 | | ISO/IEC 14496-3 Subpart 4, 4.4.1 */ |
708 | 0 | FDKwriteBits(asc, extFlg, |
709 | 0 | 1); /* Extension Flag: Shall be 1 for aot = 17,19,20,21,22,23 */ |
710 | | |
711 | | /* Write PCE if channel config is not 1-7 */ |
712 | 0 | if (getChannelConfig(config->channelMode, config->channelConfigZero) == 0) { |
713 | 0 | transportEnc_writePCE(asc, config->channelMode, config->samplingRate, 0, 1, |
714 | 0 | config->matrixMixdownA, |
715 | 0 | (config->flags & CC_PSEUDO_SURROUND) ? 1 : 0, |
716 | 0 | alignAnchor); |
717 | 0 | } |
718 | 0 | if ((aot == AOT_AAC_SCAL) || (aot == AOT_ER_AAC_SCAL)) { |
719 | 0 | FDKwriteBits(asc, 0, 3); /* layerNr */ |
720 | 0 | } |
721 | 0 | if (extFlg) { |
722 | 0 | if (aot == AOT_ER_BSAC) { |
723 | 0 | FDKwriteBits(asc, config->BSACnumOfSubFrame, 5); /* numOfSubFrame */ |
724 | 0 | FDKwriteBits(asc, config->BSAClayerLength, 11); /* layer_length */ |
725 | 0 | } |
726 | 0 | if ((aot == AOT_ER_AAC_LC) || (aot == AOT_ER_AAC_LTP) || |
727 | 0 | (aot == AOT_ER_AAC_SCAL) || (aot == AOT_ER_AAC_LD)) { |
728 | 0 | FDKwriteBits(asc, (config->flags & CC_VCB11) ? 1 : 0, |
729 | 0 | 1); /* aacSectionDataResillienceFlag */ |
730 | 0 | FDKwriteBits(asc, (config->flags & CC_RVLC) ? 1 : 0, |
731 | 0 | 1); /* aacScaleFactorDataResillienceFlag */ |
732 | 0 | FDKwriteBits(asc, (config->flags & CC_HCR) ? 1 : 0, |
733 | 0 | 1); /* aacSpectralDataResillienceFlag */ |
734 | 0 | } |
735 | 0 | FDKwriteBits(asc, 0, 1); /* extensionFlag3: reserved. Shall be '0' */ |
736 | 0 | } |
737 | 0 | return 0; |
738 | 0 | } |
739 | | |
740 | | static int transportEnc_writeELDSpecificConfig(HANDLE_FDK_BITSTREAM hBs, |
741 | | CODER_CONFIG *config, |
742 | | int epConfig, |
743 | 0 | CSTpCallBacks *cb) { |
744 | 0 | UINT frameLengthFlag = 0; |
745 | 0 | switch (config->samplesPerFrame) { |
746 | 0 | case 512: |
747 | 0 | case 256: |
748 | 0 | case 128: |
749 | 0 | case 64: |
750 | 0 | frameLengthFlag = 0; |
751 | 0 | break; |
752 | 0 | case 480: |
753 | 0 | case 240: |
754 | 0 | case 160: |
755 | 0 | case 120: |
756 | 0 | case 60: |
757 | 0 | frameLengthFlag = 1; |
758 | 0 | break; |
759 | 0 | } |
760 | | |
761 | 0 | FDKwriteBits(hBs, frameLengthFlag, 1); |
762 | |
|
763 | 0 | FDKwriteBits(hBs, (config->flags & CC_VCB11) ? 1 : 0, 1); |
764 | 0 | FDKwriteBits(hBs, (config->flags & CC_RVLC) ? 1 : 0, 1); |
765 | 0 | FDKwriteBits(hBs, (config->flags & CC_HCR) ? 1 : 0, 1); |
766 | |
|
767 | 0 | FDKwriteBits(hBs, (config->flags & CC_SBR) ? 1 : 0, 1); /* SBR header flag */ |
768 | 0 | if ((config->flags & CC_SBR)) { |
769 | 0 | FDKwriteBits(hBs, (config->samplingRate == config->extSamplingRate) ? 0 : 1, |
770 | 0 | 1); /* Samplerate Flag */ |
771 | 0 | FDKwriteBits(hBs, (config->flags & CC_SBRCRC) ? 1 : 0, 1); /* SBR CRC flag*/ |
772 | |
|
773 | 0 | if (cb->cbSbr != NULL) { |
774 | 0 | const PCE_CONFIGURATION *pPce; |
775 | 0 | int e, sbrElementIndex = 0; |
776 | |
|
777 | 0 | pPce = getPceEntry(config->channelMode); |
778 | |
|
779 | 0 | for (e = 0; e < pPce->num_front_channel_elements + |
780 | 0 | pPce->num_side_channel_elements + |
781 | 0 | pPce->num_back_channel_elements + |
782 | 0 | pPce->num_lfe_channel_elements; |
783 | 0 | e++) { |
784 | 0 | if ((pPce->pEl_type[e] == ID_SCE) || (pPce->pEl_type[e] == ID_CPE)) { |
785 | 0 | cb->cbSbr(cb->cbSbrData, hBs, 0, 0, 0, config->aot, pPce->pEl_type[e], |
786 | 0 | sbrElementIndex, 0, 0, 0, NULL, 1); |
787 | 0 | sbrElementIndex++; |
788 | 0 | } |
789 | 0 | } |
790 | 0 | } |
791 | 0 | } |
792 | |
|
793 | 0 | if ((config->flags & CC_SAC) && (cb->cbSsc != NULL)) { |
794 | 0 | FDKwriteBits(hBs, ELDEXT_LDSAC, 4); |
795 | |
|
796 | 0 | const INT eldExtLen = |
797 | 0 | (cb->cbSsc(cb->cbSscData, NULL, config->aot, config->extSamplingRate, 0, |
798 | 0 | 0, 0, 0, 0, 0, NULL) + |
799 | 0 | 7) >> |
800 | 0 | 3; |
801 | 0 | INT cnt = eldExtLen; |
802 | |
|
803 | 0 | if (cnt < 0xF) { |
804 | 0 | FDKwriteBits(hBs, cnt, 4); |
805 | 0 | } else { |
806 | 0 | FDKwriteBits(hBs, 0xF, 4); |
807 | 0 | cnt -= 0xF; |
808 | |
|
809 | 0 | if (cnt < 0xFF) { |
810 | 0 | FDKwriteBits(hBs, cnt, 8); |
811 | 0 | } else { |
812 | 0 | FDKwriteBits(hBs, 0xFF, 8); |
813 | 0 | cnt -= 0xFF; |
814 | |
|
815 | 0 | FDK_ASSERT(cnt <= 0xFFFF); |
816 | 0 | FDKwriteBits(hBs, cnt, 16); |
817 | 0 | } |
818 | 0 | } |
819 | | |
820 | 0 | cb->cbSsc(cb->cbSscData, hBs, config->aot, config->extSamplingRate, 0, 0, 0, |
821 | 0 | 0, 0, 0, NULL); |
822 | 0 | } |
823 | | |
824 | 0 | if (config->downscaleSamplingRate != 0 && |
825 | 0 | config->downscaleSamplingRate != config->extSamplingRate) { |
826 | | /* downscale active */ |
827 | | |
828 | | /* eldExtLenDsc: Number of bytes for the ELD downscale extension (srIdx |
829 | | needs 1 byte |
830 | | + downscaleSamplingRate needs additional 3 bytes) */ |
831 | 0 | int eldExtLenDsc = 1; |
832 | 0 | int downscaleSamplingRate = config->downscaleSamplingRate; |
833 | 0 | FDKwriteBits(hBs, ELDEXT_DOWNSCALEINFO, 4); /* ELDEXT_DOWNSCALEINFO */ |
834 | |
|
835 | 0 | if ((downscaleSamplingRate != 96000) && (downscaleSamplingRate != 88200) && |
836 | 0 | (downscaleSamplingRate != 64000) && (downscaleSamplingRate != 48000) && |
837 | 0 | (downscaleSamplingRate != 44100) && (downscaleSamplingRate != 32000) && |
838 | 0 | (downscaleSamplingRate != 24000) && (downscaleSamplingRate != 22050) && |
839 | 0 | (downscaleSamplingRate != 16000) && (downscaleSamplingRate != 12000) && |
840 | 0 | (downscaleSamplingRate != 11025) && (downscaleSamplingRate != 8000) && |
841 | 0 | (downscaleSamplingRate != 7350)) { |
842 | 0 | eldExtLenDsc = 4; /* length extends to 4 if downscaleSamplingRate's value |
843 | | is not one of the listed values */ |
844 | 0 | } |
845 | |
|
846 | 0 | FDKwriteBits(hBs, eldExtLenDsc, 4); |
847 | 0 | writeSampleRate(hBs, downscaleSamplingRate, 4); |
848 | 0 | FDKwriteBits(hBs, 0x0, 4); /* fill_nibble */ |
849 | 0 | } |
850 | |
|
851 | 0 | FDKwriteBits(hBs, ELDEXT_TERM, 4); /* ELDEXT_TERM */ |
852 | |
|
853 | 0 | return 0; |
854 | 0 | } |
855 | | |
856 | | static int transportEnc_writeUsacSpecificConfig(HANDLE_FDK_BITSTREAM hBs, |
857 | | int extFlag, CODER_CONFIG *cc, |
858 | 0 | CSTpCallBacks *cb) { |
859 | 0 | FDK_BITSTREAM usacConf; |
860 | 0 | int usacConfigBits = cc->rawConfigBits; |
861 | |
|
862 | 0 | if ((usacConfigBits <= 0) || |
863 | 0 | ((usacConfigBits + 7) / 8 > (int)sizeof(cc->rawConfig))) { |
864 | 0 | return TRANSPORTENC_UNSUPPORTED_FORMAT; |
865 | 0 | } |
866 | 0 | FDKinitBitStream(&usacConf, cc->rawConfig, BUFSIZE_DUMMY_VALUE, |
867 | 0 | usacConfigBits, BS_READER); |
868 | |
|
869 | 0 | for (; usacConfigBits > 0; usacConfigBits--) { |
870 | 0 | UINT tmp = FDKreadBit(&usacConf); |
871 | 0 | FDKwriteBits(hBs, tmp, 1); |
872 | 0 | } |
873 | 0 | FDKsyncCache(hBs); |
874 | |
|
875 | 0 | return TRANSPORTENC_OK; |
876 | 0 | } |
877 | | |
878 | | int transportEnc_writeASC(HANDLE_FDK_BITSTREAM asc, CODER_CONFIG *config, |
879 | 0 | CSTpCallBacks *cb) { |
880 | 0 | UINT extFlag = 0; |
881 | 0 | int err; |
882 | 0 | int epConfig = 0; |
883 | | |
884 | | /* Required for the PCE. */ |
885 | 0 | UINT alignAnchor = FDKgetValidBits(asc); |
886 | | |
887 | | /* Extension Flag: Shall be 1 for aot = 17,19,20,21,22,23,39 */ |
888 | 0 | switch (config->aot) { |
889 | 0 | case AOT_ER_AAC_LC: |
890 | 0 | case AOT_ER_AAC_LTP: |
891 | 0 | case AOT_ER_AAC_SCAL: |
892 | 0 | case AOT_ER_TWIN_VQ: |
893 | 0 | case AOT_ER_BSAC: |
894 | 0 | case AOT_ER_AAC_LD: |
895 | 0 | case AOT_ER_AAC_ELD: |
896 | 0 | case AOT_USAC: |
897 | 0 | extFlag = 1; |
898 | 0 | break; |
899 | 0 | default: |
900 | 0 | break; |
901 | 0 | } |
902 | | |
903 | 0 | if (config->sbrSignaling == SIG_EXPLICIT_HIERARCHICAL && config->sbrPresent) |
904 | 0 | writeAot(asc, config->extAOT); |
905 | 0 | else |
906 | 0 | writeAot(asc, config->aot); |
907 | | |
908 | | /* In case of USAC it is the output not the core sampling rate */ |
909 | 0 | writeSampleRate(asc, config->samplingRate, 4); |
910 | | |
911 | | /* Try to guess a reasonable channel mode if not given */ |
912 | 0 | if (config->channelMode == MODE_INVALID) { |
913 | 0 | config->channelMode = transportEnc_GetChannelMode(config->noChannels); |
914 | 0 | if (config->channelMode == MODE_INVALID) return -1; |
915 | 0 | } |
916 | | |
917 | 0 | FDKwriteBits( |
918 | 0 | asc, getChannelConfig(config->channelMode, config->channelConfigZero), 4); |
919 | |
|
920 | 0 | if (config->sbrSignaling == SIG_EXPLICIT_HIERARCHICAL && config->sbrPresent) { |
921 | 0 | writeSampleRate(asc, config->extSamplingRate, 4); |
922 | 0 | writeAot(asc, config->aot); |
923 | 0 | } |
924 | |
|
925 | 0 | switch (config->aot) { |
926 | 0 | case AOT_AAC_MAIN: |
927 | 0 | case AOT_AAC_LC: |
928 | 0 | case AOT_AAC_SSR: |
929 | 0 | case AOT_AAC_LTP: |
930 | 0 | case AOT_AAC_SCAL: |
931 | 0 | case AOT_TWIN_VQ: |
932 | 0 | case AOT_ER_AAC_LC: |
933 | 0 | case AOT_ER_AAC_LTP: |
934 | 0 | case AOT_ER_AAC_SCAL: |
935 | 0 | case AOT_ER_TWIN_VQ: |
936 | 0 | case AOT_ER_BSAC: |
937 | 0 | case AOT_ER_AAC_LD: |
938 | 0 | err = |
939 | 0 | transportEnc_writeGASpecificConfig(asc, config, extFlag, alignAnchor); |
940 | 0 | if (err) return err; |
941 | 0 | break; |
942 | 0 | case AOT_ER_AAC_ELD: |
943 | 0 | err = transportEnc_writeELDSpecificConfig(asc, config, epConfig, cb); |
944 | 0 | if (err) return err; |
945 | 0 | break; |
946 | 0 | case AOT_USAC: |
947 | 0 | err = transportEnc_writeUsacSpecificConfig(asc, extFlag, config, cb); |
948 | 0 | if (err) { |
949 | 0 | return err; |
950 | 0 | } |
951 | 0 | break; |
952 | 0 | default: |
953 | 0 | return -1; |
954 | 0 | } |
955 | | |
956 | 0 | switch (config->aot) { |
957 | 0 | case AOT_ER_AAC_LC: |
958 | 0 | case AOT_ER_AAC_LTP: |
959 | 0 | case AOT_ER_AAC_SCAL: |
960 | 0 | case AOT_ER_TWIN_VQ: |
961 | 0 | case AOT_ER_BSAC: |
962 | 0 | case AOT_ER_AAC_LD: |
963 | 0 | case AOT_ER_CELP: |
964 | 0 | case AOT_ER_HVXC: |
965 | 0 | case AOT_ER_HILN: |
966 | 0 | case AOT_ER_PARA: |
967 | 0 | case AOT_ER_AAC_ELD: |
968 | 0 | FDKwriteBits(asc, 0, 2); /* epconfig 0 */ |
969 | 0 | break; |
970 | 0 | default: |
971 | 0 | break; |
972 | 0 | } |
973 | | |
974 | | /* backward compatible explicit signaling of extension AOT */ |
975 | 0 | if (config->sbrSignaling == SIG_EXPLICIT_BW_COMPATIBLE) { |
976 | 0 | TP_ASC_EXTENSION_ID ascExtId = ASCEXT_UNKOWN; |
977 | |
|
978 | 0 | if (config->sbrPresent) { |
979 | 0 | ascExtId = ASCEXT_SBR; |
980 | 0 | FDKwriteBits(asc, ascExtId, 11); |
981 | 0 | writeAot(asc, config->extAOT); |
982 | 0 | FDKwriteBits(asc, 1, 1); /* sbrPresentFlag=1 */ |
983 | 0 | writeSampleRate(asc, config->extSamplingRate, 4); |
984 | 0 | if (config->psPresent) { |
985 | 0 | ascExtId = ASCEXT_PS; |
986 | 0 | FDKwriteBits(asc, ascExtId, 11); |
987 | 0 | FDKwriteBits(asc, 1, 1); /* psPresentFlag=1 */ |
988 | 0 | } |
989 | 0 | } |
990 | 0 | } |
991 | | |
992 | | /* Make sure all bits are sync'ed */ |
993 | 0 | FDKsyncCache(asc); |
994 | |
|
995 | 0 | return 0; |
996 | 0 | } |