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