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 - 2018 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 surround 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: Encoder Library Interface
100*e5436536SAndroid Build Coastguard Worker Bitstream Writer
101*e5436536SAndroid Build Coastguard Worker
102*e5436536SAndroid Build Coastguard Worker *******************************************************************************/
103*e5436536SAndroid Build Coastguard Worker
104*e5436536SAndroid Build Coastguard Worker /* Includes ******************************************************************/
105*e5436536SAndroid Build Coastguard Worker #include "sacenc_bitstream.h"
106*e5436536SAndroid Build Coastguard Worker #include "sacenc_const.h"
107*e5436536SAndroid Build Coastguard Worker
108*e5436536SAndroid Build Coastguard Worker #include "genericStds.h"
109*e5436536SAndroid Build Coastguard Worker #include "common_fix.h"
110*e5436536SAndroid Build Coastguard Worker
111*e5436536SAndroid Build Coastguard Worker #include "FDK_matrixCalloc.h"
112*e5436536SAndroid Build Coastguard Worker #include "sacenc_nlc_enc.h"
113*e5436536SAndroid Build Coastguard Worker
114*e5436536SAndroid Build Coastguard Worker /* Defines *******************************************************************/
115*e5436536SAndroid Build Coastguard Worker #define MAX_FREQ_RES_INDEX 8
116*e5436536SAndroid Build Coastguard Worker #define MAX_SAMPLING_FREQUENCY_INDEX 13
117*e5436536SAndroid Build Coastguard Worker #define SAMPLING_FREQUENCY_INDEX_ESCAPE 15
118*e5436536SAndroid Build Coastguard Worker
119*e5436536SAndroid Build Coastguard Worker /* Data Types ****************************************************************/
120*e5436536SAndroid Build Coastguard Worker typedef struct {
121*e5436536SAndroid Build Coastguard Worker SCHAR cld_old[SACENC_MAX_NUM_BOXES][MAX_NUM_BINS];
122*e5436536SAndroid Build Coastguard Worker SCHAR icc_old[SACENC_MAX_NUM_BOXES][MAX_NUM_BINS];
123*e5436536SAndroid Build Coastguard Worker UCHAR quantCoarseCldPrev[SACENC_MAX_NUM_BOXES][MAX_NUM_PARAMS];
124*e5436536SAndroid Build Coastguard Worker UCHAR quantCoarseIccPrev[SACENC_MAX_NUM_BOXES][MAX_NUM_PARAMS];
125*e5436536SAndroid Build Coastguard Worker
126*e5436536SAndroid Build Coastguard Worker } PREV_OTTDATA;
127*e5436536SAndroid Build Coastguard Worker
128*e5436536SAndroid Build Coastguard Worker typedef struct {
129*e5436536SAndroid Build Coastguard Worker PREV_OTTDATA prevOttData;
130*e5436536SAndroid Build Coastguard Worker
131*e5436536SAndroid Build Coastguard Worker } STATIC_SPATIALFRAME;
132*e5436536SAndroid Build Coastguard Worker
133*e5436536SAndroid Build Coastguard Worker typedef struct BSF_INSTANCE {
134*e5436536SAndroid Build Coastguard Worker SPATIALSPECIFICCONFIG spatialSpecificConfig;
135*e5436536SAndroid Build Coastguard Worker SPATIALFRAME frame;
136*e5436536SAndroid Build Coastguard Worker STATIC_SPATIALFRAME prevFrameData;
137*e5436536SAndroid Build Coastguard Worker
138*e5436536SAndroid Build Coastguard Worker } BSF_INSTANCE;
139*e5436536SAndroid Build Coastguard Worker
140*e5436536SAndroid Build Coastguard Worker /* Constants *****************************************************************/
141*e5436536SAndroid Build Coastguard Worker static const INT SampleRateTable[MAX_SAMPLING_FREQUENCY_INDEX] = {
142*e5436536SAndroid Build Coastguard Worker 96000, 88200, 64000, 48000, 44100, 32000, 24000,
143*e5436536SAndroid Build Coastguard Worker 22050, 16000, 12000, 11025, 8000, 7350};
144*e5436536SAndroid Build Coastguard Worker
145*e5436536SAndroid Build Coastguard Worker static const UCHAR FreqResBinTable_LD[MAX_FREQ_RES_INDEX] = {0, 23, 15, 12,
146*e5436536SAndroid Build Coastguard Worker 9, 7, 5, 4};
147*e5436536SAndroid Build Coastguard Worker static const UCHAR FreqResStrideTable_LD[] = {1, 2, 5, 23};
148*e5436536SAndroid Build Coastguard Worker
149*e5436536SAndroid Build Coastguard Worker /* Function / Class Declarations *********************************************/
150*e5436536SAndroid Build Coastguard Worker
151*e5436536SAndroid Build Coastguard Worker /* Function / Class Definition ***********************************************/
DuplicateLosslessData(const INT startBox,const INT stopBox,const LOSSLESSDATA * const hLosslessDataFrom,const INT setFrom,LOSSLESSDATA * const hLosslessDataTo,const INT setTo)152*e5436536SAndroid Build Coastguard Worker static FDK_SACENC_ERROR DuplicateLosslessData(
153*e5436536SAndroid Build Coastguard Worker const INT startBox, const INT stopBox,
154*e5436536SAndroid Build Coastguard Worker const LOSSLESSDATA *const hLosslessDataFrom, const INT setFrom,
155*e5436536SAndroid Build Coastguard Worker LOSSLESSDATA *const hLosslessDataTo, const INT setTo) {
156*e5436536SAndroid Build Coastguard Worker FDK_SACENC_ERROR error = SACENC_OK;
157*e5436536SAndroid Build Coastguard Worker
158*e5436536SAndroid Build Coastguard Worker if ((NULL == hLosslessDataFrom) || (NULL == hLosslessDataTo)) {
159*e5436536SAndroid Build Coastguard Worker error = SACENC_INVALID_HANDLE;
160*e5436536SAndroid Build Coastguard Worker } else {
161*e5436536SAndroid Build Coastguard Worker int i;
162*e5436536SAndroid Build Coastguard Worker
163*e5436536SAndroid Build Coastguard Worker for (i = startBox; i < stopBox; i++) {
164*e5436536SAndroid Build Coastguard Worker hLosslessDataTo->bsXXXDataMode[i][setTo] =
165*e5436536SAndroid Build Coastguard Worker hLosslessDataFrom->bsXXXDataMode[i][setFrom];
166*e5436536SAndroid Build Coastguard Worker hLosslessDataTo->bsDataPair[i][setTo] =
167*e5436536SAndroid Build Coastguard Worker hLosslessDataFrom->bsDataPair[i][setFrom];
168*e5436536SAndroid Build Coastguard Worker hLosslessDataTo->bsQuantCoarseXXX[i][setTo] =
169*e5436536SAndroid Build Coastguard Worker hLosslessDataFrom->bsQuantCoarseXXX[i][setFrom];
170*e5436536SAndroid Build Coastguard Worker hLosslessDataTo->bsFreqResStrideXXX[i][setTo] =
171*e5436536SAndroid Build Coastguard Worker hLosslessDataFrom->bsFreqResStrideXXX[i][setFrom];
172*e5436536SAndroid Build Coastguard Worker }
173*e5436536SAndroid Build Coastguard Worker }
174*e5436536SAndroid Build Coastguard Worker return error;
175*e5436536SAndroid Build Coastguard Worker }
176*e5436536SAndroid Build Coastguard Worker
fdk_sacenc_duplicateParameterSet(const SPATIALFRAME * const hFrom,const INT setFrom,SPATIALFRAME * const hTo,const INT setTo)177*e5436536SAndroid Build Coastguard Worker FDK_SACENC_ERROR fdk_sacenc_duplicateParameterSet(
178*e5436536SAndroid Build Coastguard Worker const SPATIALFRAME *const hFrom, const INT setFrom, SPATIALFRAME *const hTo,
179*e5436536SAndroid Build Coastguard Worker const INT setTo) {
180*e5436536SAndroid Build Coastguard Worker FDK_SACENC_ERROR error = SACENC_OK;
181*e5436536SAndroid Build Coastguard Worker
182*e5436536SAndroid Build Coastguard Worker if ((NULL == hFrom) || (NULL == hTo)) {
183*e5436536SAndroid Build Coastguard Worker error = SACENC_INVALID_HANDLE;
184*e5436536SAndroid Build Coastguard Worker } else {
185*e5436536SAndroid Build Coastguard Worker int box;
186*e5436536SAndroid Build Coastguard Worker /* Only Copy Parameter Set selective stuff */
187*e5436536SAndroid Build Coastguard Worker
188*e5436536SAndroid Build Coastguard Worker /* OTT-Data */
189*e5436536SAndroid Build Coastguard Worker for (box = 0; box < SACENC_MAX_NUM_BOXES; box++) {
190*e5436536SAndroid Build Coastguard Worker FDKmemcpy(hTo->ottData.cld[box][setTo], hFrom->ottData.cld[box][setFrom],
191*e5436536SAndroid Build Coastguard Worker sizeof(hFrom->ottData.cld[0][0]));
192*e5436536SAndroid Build Coastguard Worker FDKmemcpy(hTo->ottData.icc[box][setTo], hFrom->ottData.icc[box][setFrom],
193*e5436536SAndroid Build Coastguard Worker sizeof(hFrom->ottData.icc[0][0]));
194*e5436536SAndroid Build Coastguard Worker }
195*e5436536SAndroid Build Coastguard Worker
196*e5436536SAndroid Build Coastguard Worker /* LOSSLESSDATA */
197*e5436536SAndroid Build Coastguard Worker DuplicateLosslessData(0, SACENC_MAX_NUM_BOXES, &hFrom->CLDLosslessData,
198*e5436536SAndroid Build Coastguard Worker setFrom, &hTo->CLDLosslessData, setTo);
199*e5436536SAndroid Build Coastguard Worker DuplicateLosslessData(0, SACENC_MAX_NUM_BOXES, &hFrom->ICCLosslessData,
200*e5436536SAndroid Build Coastguard Worker setFrom, &hTo->ICCLosslessData, setTo);
201*e5436536SAndroid Build Coastguard Worker
202*e5436536SAndroid Build Coastguard Worker } /* valid handle */
203*e5436536SAndroid Build Coastguard Worker
204*e5436536SAndroid Build Coastguard Worker return error;
205*e5436536SAndroid Build Coastguard Worker }
206*e5436536SAndroid Build Coastguard Worker
207*e5436536SAndroid Build Coastguard Worker /* set frame defaults */
clearFrame(SPATIALFRAME * const pFrame)208*e5436536SAndroid Build Coastguard Worker static void clearFrame(SPATIALFRAME *const pFrame) {
209*e5436536SAndroid Build Coastguard Worker FDKmemclear(pFrame, sizeof(SPATIALFRAME));
210*e5436536SAndroid Build Coastguard Worker
211*e5436536SAndroid Build Coastguard Worker pFrame->bsIndependencyFlag = 1;
212*e5436536SAndroid Build Coastguard Worker pFrame->framingInfo.numParamSets = 1;
213*e5436536SAndroid Build Coastguard Worker }
214*e5436536SAndroid Build Coastguard Worker
fine2coarse(SCHAR * const data,const DATA_TYPE dataType,const INT startBand,const INT numBands)215*e5436536SAndroid Build Coastguard Worker static void fine2coarse(SCHAR *const data, const DATA_TYPE dataType,
216*e5436536SAndroid Build Coastguard Worker const INT startBand, const INT numBands) {
217*e5436536SAndroid Build Coastguard Worker int i;
218*e5436536SAndroid Build Coastguard Worker if (dataType == t_CLD) {
219*e5436536SAndroid Build Coastguard Worker for (i = startBand; i < startBand + numBands; i++) {
220*e5436536SAndroid Build Coastguard Worker data[i] /= 2;
221*e5436536SAndroid Build Coastguard Worker }
222*e5436536SAndroid Build Coastguard Worker } else {
223*e5436536SAndroid Build Coastguard Worker for (i = startBand; i < startBand + numBands; i++) {
224*e5436536SAndroid Build Coastguard Worker data[i] >>= 1;
225*e5436536SAndroid Build Coastguard Worker }
226*e5436536SAndroid Build Coastguard Worker }
227*e5436536SAndroid Build Coastguard Worker }
228*e5436536SAndroid Build Coastguard Worker
coarse2fine(SCHAR * const data,const DATA_TYPE dataType,const INT startBand,const INT numBands)229*e5436536SAndroid Build Coastguard Worker static void coarse2fine(SCHAR *const data, const DATA_TYPE dataType,
230*e5436536SAndroid Build Coastguard Worker const INT startBand, const INT numBands) {
231*e5436536SAndroid Build Coastguard Worker int i;
232*e5436536SAndroid Build Coastguard Worker
233*e5436536SAndroid Build Coastguard Worker for (i = startBand; i < startBand + numBands; i++) {
234*e5436536SAndroid Build Coastguard Worker data[i] <<= 1;
235*e5436536SAndroid Build Coastguard Worker }
236*e5436536SAndroid Build Coastguard Worker
237*e5436536SAndroid Build Coastguard Worker if (dataType == t_CLD) {
238*e5436536SAndroid Build Coastguard Worker for (i = startBand; i < startBand + numBands; i++) {
239*e5436536SAndroid Build Coastguard Worker if (data[i] == -14) {
240*e5436536SAndroid Build Coastguard Worker data[i] = -15;
241*e5436536SAndroid Build Coastguard Worker } else if (data[i] == 14) {
242*e5436536SAndroid Build Coastguard Worker data[i] = 15;
243*e5436536SAndroid Build Coastguard Worker }
244*e5436536SAndroid Build Coastguard Worker }
245*e5436536SAndroid Build Coastguard Worker } /* (dataType == t_CLD) */
246*e5436536SAndroid Build Coastguard Worker }
247*e5436536SAndroid Build Coastguard Worker
getBsFreqResStride(const INT index)248*e5436536SAndroid Build Coastguard Worker static UCHAR getBsFreqResStride(const INT index) {
249*e5436536SAndroid Build Coastguard Worker const UCHAR *pFreqResStrideTable = NULL;
250*e5436536SAndroid Build Coastguard Worker int freqResStrideTableSize = 0;
251*e5436536SAndroid Build Coastguard Worker
252*e5436536SAndroid Build Coastguard Worker pFreqResStrideTable = FreqResStrideTable_LD;
253*e5436536SAndroid Build Coastguard Worker freqResStrideTableSize =
254*e5436536SAndroid Build Coastguard Worker sizeof(FreqResStrideTable_LD) / sizeof(*FreqResStrideTable_LD);
255*e5436536SAndroid Build Coastguard Worker
256*e5436536SAndroid Build Coastguard Worker return (((NULL != pFreqResStrideTable) && (index >= 0) &&
257*e5436536SAndroid Build Coastguard Worker (index < freqResStrideTableSize))
258*e5436536SAndroid Build Coastguard Worker ? pFreqResStrideTable[index]
259*e5436536SAndroid Build Coastguard Worker : 1);
260*e5436536SAndroid Build Coastguard Worker }
261*e5436536SAndroid Build Coastguard Worker
262*e5436536SAndroid Build Coastguard Worker /* write data to bitstream */
ecData(HANDLE_FDK_BITSTREAM bitstream,SCHAR data[MAX_NUM_PARAMS][MAX_NUM_BINS],SCHAR oldData[MAX_NUM_BINS],UCHAR quantCoarseXXXprev[MAX_NUM_PARAMS],LOSSLESSDATA * const losslessData,const DATA_TYPE dataType,const INT paramIdx,const INT numParamSets,const INT independencyFlag,const INT startBand,const INT stopBand,const INT defaultValue)263*e5436536SAndroid Build Coastguard Worker static void ecData(HANDLE_FDK_BITSTREAM bitstream,
264*e5436536SAndroid Build Coastguard Worker SCHAR data[MAX_NUM_PARAMS][MAX_NUM_BINS],
265*e5436536SAndroid Build Coastguard Worker SCHAR oldData[MAX_NUM_BINS],
266*e5436536SAndroid Build Coastguard Worker UCHAR quantCoarseXXXprev[MAX_NUM_PARAMS],
267*e5436536SAndroid Build Coastguard Worker LOSSLESSDATA *const losslessData, const DATA_TYPE dataType,
268*e5436536SAndroid Build Coastguard Worker const INT paramIdx, const INT numParamSets,
269*e5436536SAndroid Build Coastguard Worker const INT independencyFlag, const INT startBand,
270*e5436536SAndroid Build Coastguard Worker const INT stopBand, const INT defaultValue) {
271*e5436536SAndroid Build Coastguard Worker int ps, pb, strOffset, pbStride, dataBands, i;
272*e5436536SAndroid Build Coastguard Worker int aStrides[MAX_NUM_BINS + 1] = {0};
273*e5436536SAndroid Build Coastguard Worker SHORT cmpIdxData[2][MAX_NUM_BINS] = {{0}};
274*e5436536SAndroid Build Coastguard Worker SHORT cmpOldData[MAX_NUM_BINS] = {0};
275*e5436536SAndroid Build Coastguard Worker
276*e5436536SAndroid Build Coastguard Worker /* bsXXXDataMode */
277*e5436536SAndroid Build Coastguard Worker if (independencyFlag || (losslessData->bsQuantCoarseXXX[paramIdx][0] !=
278*e5436536SAndroid Build Coastguard Worker quantCoarseXXXprev[paramIdx])) {
279*e5436536SAndroid Build Coastguard Worker losslessData->bsXXXDataMode[paramIdx][0] = FINECOARSE;
280*e5436536SAndroid Build Coastguard Worker } else {
281*e5436536SAndroid Build Coastguard Worker losslessData->bsXXXDataMode[paramIdx][0] = KEEP;
282*e5436536SAndroid Build Coastguard Worker for (i = startBand; i < stopBand; i++) {
283*e5436536SAndroid Build Coastguard Worker if (data[0][i] != oldData[i]) {
284*e5436536SAndroid Build Coastguard Worker losslessData->bsXXXDataMode[paramIdx][0] = FINECOARSE;
285*e5436536SAndroid Build Coastguard Worker break;
286*e5436536SAndroid Build Coastguard Worker }
287*e5436536SAndroid Build Coastguard Worker }
288*e5436536SAndroid Build Coastguard Worker }
289*e5436536SAndroid Build Coastguard Worker
290*e5436536SAndroid Build Coastguard Worker FDKwriteBits(bitstream, losslessData->bsXXXDataMode[paramIdx][0], 2);
291*e5436536SAndroid Build Coastguard Worker
292*e5436536SAndroid Build Coastguard Worker for (ps = 1; ps < numParamSets; ps++) {
293*e5436536SAndroid Build Coastguard Worker if (losslessData->bsQuantCoarseXXX[paramIdx][ps] !=
294*e5436536SAndroid Build Coastguard Worker losslessData->bsQuantCoarseXXX[paramIdx][ps - 1]) {
295*e5436536SAndroid Build Coastguard Worker losslessData->bsXXXDataMode[paramIdx][ps] = FINECOARSE;
296*e5436536SAndroid Build Coastguard Worker } else {
297*e5436536SAndroid Build Coastguard Worker losslessData->bsXXXDataMode[paramIdx][ps] = KEEP;
298*e5436536SAndroid Build Coastguard Worker for (i = startBand; i < stopBand; i++) {
299*e5436536SAndroid Build Coastguard Worker if (data[ps][i] != data[ps - 1][i]) {
300*e5436536SAndroid Build Coastguard Worker losslessData->bsXXXDataMode[paramIdx][ps] = FINECOARSE;
301*e5436536SAndroid Build Coastguard Worker break;
302*e5436536SAndroid Build Coastguard Worker }
303*e5436536SAndroid Build Coastguard Worker }
304*e5436536SAndroid Build Coastguard Worker }
305*e5436536SAndroid Build Coastguard Worker
306*e5436536SAndroid Build Coastguard Worker FDKwriteBits(bitstream, losslessData->bsXXXDataMode[paramIdx][ps], 2);
307*e5436536SAndroid Build Coastguard Worker } /* for ps */
308*e5436536SAndroid Build Coastguard Worker
309*e5436536SAndroid Build Coastguard Worker /* Create data pairs if possible */
310*e5436536SAndroid Build Coastguard Worker for (ps = 0; ps < (numParamSets - 1); ps++) {
311*e5436536SAndroid Build Coastguard Worker if (losslessData->bsXXXDataMode[paramIdx][ps] == FINECOARSE) {
312*e5436536SAndroid Build Coastguard Worker /* Check if next parameter set is FINCOARSE */
313*e5436536SAndroid Build Coastguard Worker if (losslessData->bsXXXDataMode[paramIdx][ps + 1] == FINECOARSE) {
314*e5436536SAndroid Build Coastguard Worker /* We have to check if ps and ps+1 use the same bsXXXQuantMode */
315*e5436536SAndroid Build Coastguard Worker /* and also have the same stride */
316*e5436536SAndroid Build Coastguard Worker if ((losslessData->bsQuantCoarseXXX[paramIdx][ps + 1] ==
317*e5436536SAndroid Build Coastguard Worker losslessData->bsQuantCoarseXXX[paramIdx][ps]) &&
318*e5436536SAndroid Build Coastguard Worker (losslessData->bsFreqResStrideXXX[paramIdx][ps + 1] ==
319*e5436536SAndroid Build Coastguard Worker losslessData->bsFreqResStrideXXX[paramIdx][ps])) {
320*e5436536SAndroid Build Coastguard Worker losslessData->bsDataPair[paramIdx][ps] = 1;
321*e5436536SAndroid Build Coastguard Worker losslessData->bsDataPair[paramIdx][ps + 1] = 1;
322*e5436536SAndroid Build Coastguard Worker
323*e5436536SAndroid Build Coastguard Worker /* We have a data pair -> Jump to the ps after next ps*/
324*e5436536SAndroid Build Coastguard Worker ps++;
325*e5436536SAndroid Build Coastguard Worker continue;
326*e5436536SAndroid Build Coastguard Worker }
327*e5436536SAndroid Build Coastguard Worker }
328*e5436536SAndroid Build Coastguard Worker /* dataMode of next ps is not FINECOARSE or does not use the same
329*e5436536SAndroid Build Coastguard Worker * bsXXXQuantMode/stride */
330*e5436536SAndroid Build Coastguard Worker /* -> no dataPair possible */
331*e5436536SAndroid Build Coastguard Worker losslessData->bsDataPair[paramIdx][ps] = 0;
332*e5436536SAndroid Build Coastguard Worker
333*e5436536SAndroid Build Coastguard Worker /* Initialize ps after next ps to Zero (only important for the last
334*e5436536SAndroid Build Coastguard Worker * parameter set) */
335*e5436536SAndroid Build Coastguard Worker losslessData->bsDataPair[paramIdx][ps + 1] = 0;
336*e5436536SAndroid Build Coastguard Worker } else {
337*e5436536SAndroid Build Coastguard Worker /* No FINECOARSE -> no data pair possible */
338*e5436536SAndroid Build Coastguard Worker losslessData->bsDataPair[paramIdx][ps] = 0;
339*e5436536SAndroid Build Coastguard Worker
340*e5436536SAndroid Build Coastguard Worker /* Initialize ps after next ps to Zero (only important for the last
341*e5436536SAndroid Build Coastguard Worker * parameter set) */
342*e5436536SAndroid Build Coastguard Worker losslessData->bsDataPair[paramIdx][ps + 1] = 0;
343*e5436536SAndroid Build Coastguard Worker }
344*e5436536SAndroid Build Coastguard Worker } /* for ps */
345*e5436536SAndroid Build Coastguard Worker
346*e5436536SAndroid Build Coastguard Worker for (ps = 0; ps < numParamSets; ps++) {
347*e5436536SAndroid Build Coastguard Worker if (losslessData->bsXXXDataMode[paramIdx][ps] == DEFAULT) {
348*e5436536SAndroid Build Coastguard Worker /* Prepare old data */
349*e5436536SAndroid Build Coastguard Worker for (i = startBand; i < stopBand; i++) {
350*e5436536SAndroid Build Coastguard Worker oldData[i] = defaultValue;
351*e5436536SAndroid Build Coastguard Worker }
352*e5436536SAndroid Build Coastguard Worker quantCoarseXXXprev[paramIdx] = 0; /* Default data are always fine */
353*e5436536SAndroid Build Coastguard Worker }
354*e5436536SAndroid Build Coastguard Worker
355*e5436536SAndroid Build Coastguard Worker if (losslessData->bsXXXDataMode[paramIdx][ps] == FINECOARSE) {
356*e5436536SAndroid Build Coastguard Worker FDKwriteBits(bitstream, losslessData->bsDataPair[paramIdx][ps], 1);
357*e5436536SAndroid Build Coastguard Worker FDKwriteBits(bitstream, losslessData->bsQuantCoarseXXX[paramIdx][ps], 1);
358*e5436536SAndroid Build Coastguard Worker FDKwriteBits(bitstream, losslessData->bsFreqResStrideXXX[paramIdx][ps],
359*e5436536SAndroid Build Coastguard Worker 2);
360*e5436536SAndroid Build Coastguard Worker
361*e5436536SAndroid Build Coastguard Worker if (losslessData->bsQuantCoarseXXX[paramIdx][ps] !=
362*e5436536SAndroid Build Coastguard Worker quantCoarseXXXprev[paramIdx]) {
363*e5436536SAndroid Build Coastguard Worker if (quantCoarseXXXprev[paramIdx]) {
364*e5436536SAndroid Build Coastguard Worker coarse2fine(oldData, dataType, startBand, stopBand - startBand);
365*e5436536SAndroid Build Coastguard Worker } else {
366*e5436536SAndroid Build Coastguard Worker fine2coarse(oldData, dataType, startBand, stopBand - startBand);
367*e5436536SAndroid Build Coastguard Worker }
368*e5436536SAndroid Build Coastguard Worker }
369*e5436536SAndroid Build Coastguard Worker
370*e5436536SAndroid Build Coastguard Worker /* Handle strides */
371*e5436536SAndroid Build Coastguard Worker pbStride =
372*e5436536SAndroid Build Coastguard Worker getBsFreqResStride(losslessData->bsFreqResStrideXXX[paramIdx][ps]);
373*e5436536SAndroid Build Coastguard Worker dataBands = (stopBand - startBand - 1) / pbStride + 1;
374*e5436536SAndroid Build Coastguard Worker
375*e5436536SAndroid Build Coastguard Worker aStrides[0] = startBand;
376*e5436536SAndroid Build Coastguard Worker for (pb = 1; pb <= dataBands; pb++) {
377*e5436536SAndroid Build Coastguard Worker aStrides[pb] = aStrides[pb - 1] + pbStride;
378*e5436536SAndroid Build Coastguard Worker }
379*e5436536SAndroid Build Coastguard Worker
380*e5436536SAndroid Build Coastguard Worker strOffset = 0;
381*e5436536SAndroid Build Coastguard Worker while (aStrides[dataBands] > stopBand) {
382*e5436536SAndroid Build Coastguard Worker if (strOffset < dataBands) {
383*e5436536SAndroid Build Coastguard Worker strOffset++;
384*e5436536SAndroid Build Coastguard Worker }
385*e5436536SAndroid Build Coastguard Worker for (i = strOffset; i <= dataBands; i++) {
386*e5436536SAndroid Build Coastguard Worker aStrides[i]--;
387*e5436536SAndroid Build Coastguard Worker }
388*e5436536SAndroid Build Coastguard Worker } /* while */
389*e5436536SAndroid Build Coastguard Worker
390*e5436536SAndroid Build Coastguard Worker for (pb = 0; pb < dataBands; pb++) {
391*e5436536SAndroid Build Coastguard Worker cmpOldData[startBand + pb] = oldData[aStrides[pb]];
392*e5436536SAndroid Build Coastguard Worker cmpIdxData[0][startBand + pb] = data[ps][aStrides[pb]];
393*e5436536SAndroid Build Coastguard Worker
394*e5436536SAndroid Build Coastguard Worker if (losslessData->bsDataPair[paramIdx][ps]) {
395*e5436536SAndroid Build Coastguard Worker cmpIdxData[1][startBand + pb] = data[ps + 1][aStrides[pb]];
396*e5436536SAndroid Build Coastguard Worker }
397*e5436536SAndroid Build Coastguard Worker } /* for pb*/
398*e5436536SAndroid Build Coastguard Worker
399*e5436536SAndroid Build Coastguard Worker /* Finally encode */
400*e5436536SAndroid Build Coastguard Worker if (losslessData->bsDataPair[paramIdx][ps]) {
401*e5436536SAndroid Build Coastguard Worker fdk_sacenc_ecDataPairEnc(bitstream, cmpIdxData, cmpOldData, dataType, 0,
402*e5436536SAndroid Build Coastguard Worker startBand, dataBands,
403*e5436536SAndroid Build Coastguard Worker losslessData->bsQuantCoarseXXX[paramIdx][ps],
404*e5436536SAndroid Build Coastguard Worker independencyFlag && (ps == 0));
405*e5436536SAndroid Build Coastguard Worker } else {
406*e5436536SAndroid Build Coastguard Worker fdk_sacenc_ecDataSingleEnc(bitstream, cmpIdxData, cmpOldData, dataType,
407*e5436536SAndroid Build Coastguard Worker 0, startBand, dataBands,
408*e5436536SAndroid Build Coastguard Worker losslessData->bsQuantCoarseXXX[paramIdx][ps],
409*e5436536SAndroid Build Coastguard Worker independencyFlag && (ps == 0));
410*e5436536SAndroid Build Coastguard Worker }
411*e5436536SAndroid Build Coastguard Worker
412*e5436536SAndroid Build Coastguard Worker /* Overwrite old data */
413*e5436536SAndroid Build Coastguard Worker for (i = startBand; i < stopBand; i++) {
414*e5436536SAndroid Build Coastguard Worker if (losslessData->bsDataPair[paramIdx][ps]) {
415*e5436536SAndroid Build Coastguard Worker oldData[i] = data[ps + 1][i];
416*e5436536SAndroid Build Coastguard Worker } else {
417*e5436536SAndroid Build Coastguard Worker oldData[i] = data[ps][i];
418*e5436536SAndroid Build Coastguard Worker }
419*e5436536SAndroid Build Coastguard Worker }
420*e5436536SAndroid Build Coastguard Worker
421*e5436536SAndroid Build Coastguard Worker quantCoarseXXXprev[paramIdx] =
422*e5436536SAndroid Build Coastguard Worker losslessData->bsQuantCoarseXXX[paramIdx][ps];
423*e5436536SAndroid Build Coastguard Worker
424*e5436536SAndroid Build Coastguard Worker /* Jump forward if we have encoded a data pair */
425*e5436536SAndroid Build Coastguard Worker if (losslessData->bsDataPair[paramIdx][ps]) {
426*e5436536SAndroid Build Coastguard Worker ps++;
427*e5436536SAndroid Build Coastguard Worker }
428*e5436536SAndroid Build Coastguard Worker
429*e5436536SAndroid Build Coastguard Worker } /* if (losslessData->bsXXXDataMode[paramIdx][ps] == FINECOARSE ) */
430*e5436536SAndroid Build Coastguard Worker } /* for ps */
431*e5436536SAndroid Build Coastguard Worker }
432*e5436536SAndroid Build Coastguard Worker
433*e5436536SAndroid Build Coastguard Worker /****************************************************************************/
434*e5436536SAndroid Build Coastguard Worker /* Bitstream formatter interface functions */
435*e5436536SAndroid Build Coastguard Worker /****************************************************************************/
getBsFreqResIndex(const INT numBands,INT * const pbsFreqResIndex)436*e5436536SAndroid Build Coastguard Worker static FDK_SACENC_ERROR getBsFreqResIndex(const INT numBands,
437*e5436536SAndroid Build Coastguard Worker INT *const pbsFreqResIndex) {
438*e5436536SAndroid Build Coastguard Worker FDK_SACENC_ERROR error = SACENC_OK;
439*e5436536SAndroid Build Coastguard Worker
440*e5436536SAndroid Build Coastguard Worker if (NULL == pbsFreqResIndex) {
441*e5436536SAndroid Build Coastguard Worker error = SACENC_INVALID_HANDLE;
442*e5436536SAndroid Build Coastguard Worker } else {
443*e5436536SAndroid Build Coastguard Worker const UCHAR *pFreqResBinTable = FreqResBinTable_LD;
444*e5436536SAndroid Build Coastguard Worker int i;
445*e5436536SAndroid Build Coastguard Worker *pbsFreqResIndex = -1;
446*e5436536SAndroid Build Coastguard Worker
447*e5436536SAndroid Build Coastguard Worker for (i = 0; i < MAX_FREQ_RES_INDEX; i++) {
448*e5436536SAndroid Build Coastguard Worker if (numBands == pFreqResBinTable[i]) {
449*e5436536SAndroid Build Coastguard Worker *pbsFreqResIndex = i;
450*e5436536SAndroid Build Coastguard Worker break;
451*e5436536SAndroid Build Coastguard Worker }
452*e5436536SAndroid Build Coastguard Worker }
453*e5436536SAndroid Build Coastguard Worker if (*pbsFreqResIndex < 0 || *pbsFreqResIndex >= MAX_FREQ_RES_INDEX) {
454*e5436536SAndroid Build Coastguard Worker error = SACENC_INVALID_CONFIG;
455*e5436536SAndroid Build Coastguard Worker }
456*e5436536SAndroid Build Coastguard Worker }
457*e5436536SAndroid Build Coastguard Worker return error;
458*e5436536SAndroid Build Coastguard Worker }
459*e5436536SAndroid Build Coastguard Worker
getSamplingFrequencyIndex(const INT bsSamplingFrequency,INT * const pbsSamplingFrequencyIndex)460*e5436536SAndroid Build Coastguard Worker static FDK_SACENC_ERROR getSamplingFrequencyIndex(
461*e5436536SAndroid Build Coastguard Worker const INT bsSamplingFrequency, INT *const pbsSamplingFrequencyIndex) {
462*e5436536SAndroid Build Coastguard Worker FDK_SACENC_ERROR error = SACENC_OK;
463*e5436536SAndroid Build Coastguard Worker
464*e5436536SAndroid Build Coastguard Worker if (NULL == pbsSamplingFrequencyIndex) {
465*e5436536SAndroid Build Coastguard Worker error = SACENC_INVALID_HANDLE;
466*e5436536SAndroid Build Coastguard Worker } else {
467*e5436536SAndroid Build Coastguard Worker int i;
468*e5436536SAndroid Build Coastguard Worker *pbsSamplingFrequencyIndex = SAMPLING_FREQUENCY_INDEX_ESCAPE;
469*e5436536SAndroid Build Coastguard Worker
470*e5436536SAndroid Build Coastguard Worker for (i = 0; i < MAX_SAMPLING_FREQUENCY_INDEX; i++) {
471*e5436536SAndroid Build Coastguard Worker if (bsSamplingFrequency == SampleRateTable[i]) { /*spatial sampling rate*/
472*e5436536SAndroid Build Coastguard Worker *pbsSamplingFrequencyIndex = i;
473*e5436536SAndroid Build Coastguard Worker break;
474*e5436536SAndroid Build Coastguard Worker }
475*e5436536SAndroid Build Coastguard Worker }
476*e5436536SAndroid Build Coastguard Worker }
477*e5436536SAndroid Build Coastguard Worker return error;
478*e5436536SAndroid Build Coastguard Worker }
479*e5436536SAndroid Build Coastguard Worker
480*e5436536SAndroid Build Coastguard Worker /* destroy encoder instance */
fdk_sacenc_destroySpatialBitstreamEncoder(HANDLE_BSF_INSTANCE * selfPtr)481*e5436536SAndroid Build Coastguard Worker FDK_SACENC_ERROR fdk_sacenc_destroySpatialBitstreamEncoder(
482*e5436536SAndroid Build Coastguard Worker HANDLE_BSF_INSTANCE *selfPtr) {
483*e5436536SAndroid Build Coastguard Worker FDK_SACENC_ERROR error = SACENC_OK;
484*e5436536SAndroid Build Coastguard Worker
485*e5436536SAndroid Build Coastguard Worker if ((selfPtr == NULL) || (*selfPtr == NULL)) {
486*e5436536SAndroid Build Coastguard Worker error = SACENC_INVALID_HANDLE;
487*e5436536SAndroid Build Coastguard Worker } else {
488*e5436536SAndroid Build Coastguard Worker if (*selfPtr != NULL) {
489*e5436536SAndroid Build Coastguard Worker FDK_FREE_MEMORY_1D(*selfPtr);
490*e5436536SAndroid Build Coastguard Worker }
491*e5436536SAndroid Build Coastguard Worker }
492*e5436536SAndroid Build Coastguard Worker return error;
493*e5436536SAndroid Build Coastguard Worker }
494*e5436536SAndroid Build Coastguard Worker
495*e5436536SAndroid Build Coastguard Worker /* create encoder instance */
fdk_sacenc_createSpatialBitstreamEncoder(HANDLE_BSF_INSTANCE * selfPtr)496*e5436536SAndroid Build Coastguard Worker FDK_SACENC_ERROR fdk_sacenc_createSpatialBitstreamEncoder(
497*e5436536SAndroid Build Coastguard Worker HANDLE_BSF_INSTANCE *selfPtr) {
498*e5436536SAndroid Build Coastguard Worker FDK_SACENC_ERROR error = SACENC_OK;
499*e5436536SAndroid Build Coastguard Worker
500*e5436536SAndroid Build Coastguard Worker if (NULL == selfPtr) {
501*e5436536SAndroid Build Coastguard Worker error = SACENC_INVALID_HANDLE;
502*e5436536SAndroid Build Coastguard Worker } else {
503*e5436536SAndroid Build Coastguard Worker /* allocate encoder struct */
504*e5436536SAndroid Build Coastguard Worker FDK_ALLOCATE_MEMORY_1D(*selfPtr, 1, BSF_INSTANCE);
505*e5436536SAndroid Build Coastguard Worker }
506*e5436536SAndroid Build Coastguard Worker return error;
507*e5436536SAndroid Build Coastguard Worker
508*e5436536SAndroid Build Coastguard Worker bail:
509*e5436536SAndroid Build Coastguard Worker fdk_sacenc_destroySpatialBitstreamEncoder(selfPtr);
510*e5436536SAndroid Build Coastguard Worker return ((SACENC_OK == error) ? SACENC_MEMORY_ERROR : error);
511*e5436536SAndroid Build Coastguard Worker }
512*e5436536SAndroid Build Coastguard Worker
513*e5436536SAndroid Build Coastguard Worker /* init encoder instance */
fdk_sacenc_initSpatialBitstreamEncoder(HANDLE_BSF_INSTANCE selfPtr)514*e5436536SAndroid Build Coastguard Worker FDK_SACENC_ERROR fdk_sacenc_initSpatialBitstreamEncoder(
515*e5436536SAndroid Build Coastguard Worker HANDLE_BSF_INSTANCE selfPtr) {
516*e5436536SAndroid Build Coastguard Worker FDK_SACENC_ERROR error = SACENC_OK;
517*e5436536SAndroid Build Coastguard Worker
518*e5436536SAndroid Build Coastguard Worker if (selfPtr == NULL) {
519*e5436536SAndroid Build Coastguard Worker error = SACENC_INVALID_HANDLE;
520*e5436536SAndroid Build Coastguard Worker } else {
521*e5436536SAndroid Build Coastguard Worker /* init/clear */
522*e5436536SAndroid Build Coastguard Worker clearFrame(&selfPtr->frame);
523*e5436536SAndroid Build Coastguard Worker
524*e5436536SAndroid Build Coastguard Worker } /* valid handle */
525*e5436536SAndroid Build Coastguard Worker return error;
526*e5436536SAndroid Build Coastguard Worker }
527*e5436536SAndroid Build Coastguard Worker
528*e5436536SAndroid Build Coastguard Worker /* get SpatialSpecificConfig struct */
fdk_sacenc_getSpatialSpecificConfig(HANDLE_BSF_INSTANCE selfPtr)529*e5436536SAndroid Build Coastguard Worker SPATIALSPECIFICCONFIG *fdk_sacenc_getSpatialSpecificConfig(
530*e5436536SAndroid Build Coastguard Worker HANDLE_BSF_INSTANCE selfPtr) {
531*e5436536SAndroid Build Coastguard Worker return ((selfPtr == NULL) ? NULL : &(selfPtr->spatialSpecificConfig));
532*e5436536SAndroid Build Coastguard Worker }
533*e5436536SAndroid Build Coastguard Worker
534*e5436536SAndroid Build Coastguard Worker /* write SpatialSpecificConfig to stream */
fdk_sacenc_writeSpatialSpecificConfig(SPATIALSPECIFICCONFIG * const spatialSpecificConfig,UCHAR * const pOutputBuffer,const INT outputBufferSize,INT * const pnOutputBits)535*e5436536SAndroid Build Coastguard Worker FDK_SACENC_ERROR fdk_sacenc_writeSpatialSpecificConfig(
536*e5436536SAndroid Build Coastguard Worker SPATIALSPECIFICCONFIG *const spatialSpecificConfig,
537*e5436536SAndroid Build Coastguard Worker UCHAR *const pOutputBuffer, const INT outputBufferSize,
538*e5436536SAndroid Build Coastguard Worker INT *const pnOutputBits) {
539*e5436536SAndroid Build Coastguard Worker FDK_SACENC_ERROR error = SACENC_OK;
540*e5436536SAndroid Build Coastguard Worker INT bsSamplingFrequencyIndex = 0;
541*e5436536SAndroid Build Coastguard Worker INT bsFreqRes = 0;
542*e5436536SAndroid Build Coastguard Worker
543*e5436536SAndroid Build Coastguard Worker if ((spatialSpecificConfig == NULL) || (pOutputBuffer == NULL) ||
544*e5436536SAndroid Build Coastguard Worker (pnOutputBits == NULL)) {
545*e5436536SAndroid Build Coastguard Worker error = SACENC_INVALID_HANDLE;
546*e5436536SAndroid Build Coastguard Worker } else {
547*e5436536SAndroid Build Coastguard Worker FDK_BITSTREAM bitstream;
548*e5436536SAndroid Build Coastguard Worker
549*e5436536SAndroid Build Coastguard Worker /* Find FreqRes */
550*e5436536SAndroid Build Coastguard Worker if (SACENC_OK != (error = getBsFreqResIndex(spatialSpecificConfig->numBands,
551*e5436536SAndroid Build Coastguard Worker &bsFreqRes)))
552*e5436536SAndroid Build Coastguard Worker goto bail;
553*e5436536SAndroid Build Coastguard Worker
554*e5436536SAndroid Build Coastguard Worker /* Find SamplingFrequencyIndex */
555*e5436536SAndroid Build Coastguard Worker if (SACENC_OK != (error = getSamplingFrequencyIndex(
556*e5436536SAndroid Build Coastguard Worker spatialSpecificConfig->bsSamplingFrequency,
557*e5436536SAndroid Build Coastguard Worker &bsSamplingFrequencyIndex)))
558*e5436536SAndroid Build Coastguard Worker goto bail;
559*e5436536SAndroid Build Coastguard Worker
560*e5436536SAndroid Build Coastguard Worker /* bind extern buffer to bitstream handle */
561*e5436536SAndroid Build Coastguard Worker FDKinitBitStream(&bitstream, pOutputBuffer, outputBufferSize, 0, BS_WRITER);
562*e5436536SAndroid Build Coastguard Worker
563*e5436536SAndroid Build Coastguard Worker /****************************************************************************/
564*e5436536SAndroid Build Coastguard Worker /* write to bitstream */
565*e5436536SAndroid Build Coastguard Worker
566*e5436536SAndroid Build Coastguard Worker FDKwriteBits(&bitstream, bsSamplingFrequencyIndex, 4);
567*e5436536SAndroid Build Coastguard Worker
568*e5436536SAndroid Build Coastguard Worker if (bsSamplingFrequencyIndex == 15) {
569*e5436536SAndroid Build Coastguard Worker FDKwriteBits(&bitstream, spatialSpecificConfig->bsSamplingFrequency, 24);
570*e5436536SAndroid Build Coastguard Worker }
571*e5436536SAndroid Build Coastguard Worker
572*e5436536SAndroid Build Coastguard Worker FDKwriteBits(&bitstream, spatialSpecificConfig->bsFrameLength, 5);
573*e5436536SAndroid Build Coastguard Worker
574*e5436536SAndroid Build Coastguard Worker FDKwriteBits(&bitstream, bsFreqRes, 3);
575*e5436536SAndroid Build Coastguard Worker FDKwriteBits(&bitstream, spatialSpecificConfig->bsTreeConfig, 4);
576*e5436536SAndroid Build Coastguard Worker FDKwriteBits(&bitstream, spatialSpecificConfig->bsQuantMode, 2);
577*e5436536SAndroid Build Coastguard Worker
578*e5436536SAndroid Build Coastguard Worker FDKwriteBits(&bitstream, 0, 1); /* bsArbitraryDownmix */
579*e5436536SAndroid Build Coastguard Worker
580*e5436536SAndroid Build Coastguard Worker FDKwriteBits(&bitstream, spatialSpecificConfig->bsFixedGainDMX, 3);
581*e5436536SAndroid Build Coastguard Worker
582*e5436536SAndroid Build Coastguard Worker FDKwriteBits(&bitstream, TEMPSHAPE_OFF, 2);
583*e5436536SAndroid Build Coastguard Worker FDKwriteBits(&bitstream, spatialSpecificConfig->bsDecorrConfig, 2);
584*e5436536SAndroid Build Coastguard Worker
585*e5436536SAndroid Build Coastguard Worker FDKbyteAlign(&bitstream, 0); /* byte alignment */
586*e5436536SAndroid Build Coastguard Worker
587*e5436536SAndroid Build Coastguard Worker /* return number of valid bits in bitstream */
588*e5436536SAndroid Build Coastguard Worker if ((*pnOutputBits = FDKgetValidBits(&bitstream)) >
589*e5436536SAndroid Build Coastguard Worker (outputBufferSize * 8)) {
590*e5436536SAndroid Build Coastguard Worker error = SACENC_INVALID_CONFIG;
591*e5436536SAndroid Build Coastguard Worker goto bail;
592*e5436536SAndroid Build Coastguard Worker }
593*e5436536SAndroid Build Coastguard Worker
594*e5436536SAndroid Build Coastguard Worker /* terminate buffer with alignment */
595*e5436536SAndroid Build Coastguard Worker FDKbyteAlign(&bitstream, 0);
596*e5436536SAndroid Build Coastguard Worker
597*e5436536SAndroid Build Coastguard Worker } /* valid handle */
598*e5436536SAndroid Build Coastguard Worker
599*e5436536SAndroid Build Coastguard Worker bail:
600*e5436536SAndroid Build Coastguard Worker return error;
601*e5436536SAndroid Build Coastguard Worker }
602*e5436536SAndroid Build Coastguard Worker
603*e5436536SAndroid Build Coastguard Worker /* get SpatialFrame struct */
fdk_sacenc_getSpatialFrame(HANDLE_BSF_INSTANCE selfPtr,const SPATIALFRAME_TYPE frameType)604*e5436536SAndroid Build Coastguard Worker SPATIALFRAME *fdk_sacenc_getSpatialFrame(HANDLE_BSF_INSTANCE selfPtr,
605*e5436536SAndroid Build Coastguard Worker const SPATIALFRAME_TYPE frameType) {
606*e5436536SAndroid Build Coastguard Worker int idx = -1;
607*e5436536SAndroid Build Coastguard Worker
608*e5436536SAndroid Build Coastguard Worker switch (frameType) {
609*e5436536SAndroid Build Coastguard Worker case READ_SPATIALFRAME:
610*e5436536SAndroid Build Coastguard Worker case WRITE_SPATIALFRAME:
611*e5436536SAndroid Build Coastguard Worker idx = 0;
612*e5436536SAndroid Build Coastguard Worker break;
613*e5436536SAndroid Build Coastguard Worker default:
614*e5436536SAndroid Build Coastguard Worker idx = -1; /* invalid configuration */
615*e5436536SAndroid Build Coastguard Worker } /* switch frameType */
616*e5436536SAndroid Build Coastguard Worker
617*e5436536SAndroid Build Coastguard Worker return (((selfPtr == NULL) || (idx == -1)) ? NULL : &selfPtr->frame);
618*e5436536SAndroid Build Coastguard Worker }
619*e5436536SAndroid Build Coastguard Worker
writeFramingInfo(HANDLE_FDK_BITSTREAM hBitstream,const FRAMINGINFO * const pFramingInfo,const INT frameLength)620*e5436536SAndroid Build Coastguard Worker static FDK_SACENC_ERROR writeFramingInfo(HANDLE_FDK_BITSTREAM hBitstream,
621*e5436536SAndroid Build Coastguard Worker const FRAMINGINFO *const pFramingInfo,
622*e5436536SAndroid Build Coastguard Worker const INT frameLength) {
623*e5436536SAndroid Build Coastguard Worker FDK_SACENC_ERROR error = SACENC_OK;
624*e5436536SAndroid Build Coastguard Worker
625*e5436536SAndroid Build Coastguard Worker if ((hBitstream == NULL) || (pFramingInfo == NULL)) {
626*e5436536SAndroid Build Coastguard Worker error = SACENC_INVALID_HANDLE;
627*e5436536SAndroid Build Coastguard Worker } else {
628*e5436536SAndroid Build Coastguard Worker FDKwriteBits(hBitstream, pFramingInfo->bsFramingType, 1);
629*e5436536SAndroid Build Coastguard Worker FDKwriteBits(hBitstream, pFramingInfo->numParamSets - 1, 1);
630*e5436536SAndroid Build Coastguard Worker
631*e5436536SAndroid Build Coastguard Worker if (pFramingInfo->bsFramingType) {
632*e5436536SAndroid Build Coastguard Worker int ps = 0;
633*e5436536SAndroid Build Coastguard Worker int numParamSets = pFramingInfo->numParamSets;
634*e5436536SAndroid Build Coastguard Worker
635*e5436536SAndroid Build Coastguard Worker {
636*e5436536SAndroid Build Coastguard Worker for (ps = 0; ps < numParamSets; ps++) {
637*e5436536SAndroid Build Coastguard Worker int bitsParamSlot = 0;
638*e5436536SAndroid Build Coastguard Worker while ((1 << bitsParamSlot) < (frameLength + 1)) bitsParamSlot++;
639*e5436536SAndroid Build Coastguard Worker if (bitsParamSlot > 0)
640*e5436536SAndroid Build Coastguard Worker FDKwriteBits(hBitstream, pFramingInfo->bsParamSlots[ps],
641*e5436536SAndroid Build Coastguard Worker bitsParamSlot);
642*e5436536SAndroid Build Coastguard Worker }
643*e5436536SAndroid Build Coastguard Worker }
644*e5436536SAndroid Build Coastguard Worker } /* pFramingInfo->bsFramingType */
645*e5436536SAndroid Build Coastguard Worker } /* valid handle */
646*e5436536SAndroid Build Coastguard Worker
647*e5436536SAndroid Build Coastguard Worker return error;
648*e5436536SAndroid Build Coastguard Worker }
649*e5436536SAndroid Build Coastguard Worker
writeSmgData(HANDLE_FDK_BITSTREAM hBitstream,const SMGDATA * const pSmgData,const INT numParamSets,const INT dataBands)650*e5436536SAndroid Build Coastguard Worker static FDK_SACENC_ERROR writeSmgData(HANDLE_FDK_BITSTREAM hBitstream,
651*e5436536SAndroid Build Coastguard Worker const SMGDATA *const pSmgData,
652*e5436536SAndroid Build Coastguard Worker const INT numParamSets,
653*e5436536SAndroid Build Coastguard Worker const INT dataBands) {
654*e5436536SAndroid Build Coastguard Worker FDK_SACENC_ERROR error = SACENC_OK;
655*e5436536SAndroid Build Coastguard Worker
656*e5436536SAndroid Build Coastguard Worker if ((hBitstream == NULL) || (pSmgData == NULL)) {
657*e5436536SAndroid Build Coastguard Worker error = SACENC_INVALID_HANDLE;
658*e5436536SAndroid Build Coastguard Worker } else {
659*e5436536SAndroid Build Coastguard Worker int i, j;
660*e5436536SAndroid Build Coastguard Worker
661*e5436536SAndroid Build Coastguard Worker for (i = 0; i < numParamSets; i++) {
662*e5436536SAndroid Build Coastguard Worker FDKwriteBits(hBitstream, pSmgData->bsSmoothMode[i], 2);
663*e5436536SAndroid Build Coastguard Worker
664*e5436536SAndroid Build Coastguard Worker if (pSmgData->bsSmoothMode[i] >= 2) {
665*e5436536SAndroid Build Coastguard Worker FDKwriteBits(hBitstream, pSmgData->bsSmoothTime[i], 2);
666*e5436536SAndroid Build Coastguard Worker }
667*e5436536SAndroid Build Coastguard Worker if (pSmgData->bsSmoothMode[i] == 3) {
668*e5436536SAndroid Build Coastguard Worker const int stride = getBsFreqResStride(pSmgData->bsFreqResStride[i]);
669*e5436536SAndroid Build Coastguard Worker FDKwriteBits(hBitstream, pSmgData->bsFreqResStride[i], 2);
670*e5436536SAndroid Build Coastguard Worker for (j = 0; j < dataBands; j += stride) {
671*e5436536SAndroid Build Coastguard Worker FDKwriteBits(hBitstream, pSmgData->bsSmgData[i][j], 1);
672*e5436536SAndroid Build Coastguard Worker }
673*e5436536SAndroid Build Coastguard Worker }
674*e5436536SAndroid Build Coastguard Worker } /* for i */
675*e5436536SAndroid Build Coastguard Worker } /* valid handle */
676*e5436536SAndroid Build Coastguard Worker
677*e5436536SAndroid Build Coastguard Worker return error;
678*e5436536SAndroid Build Coastguard Worker }
679*e5436536SAndroid Build Coastguard Worker
writeOttData(HANDLE_FDK_BITSTREAM hBitstream,PREV_OTTDATA * const pPrevOttData,OTTDATA * const pOttData,const OTTCONFIG ottConfig[SACENC_MAX_NUM_BOXES],LOSSLESSDATA * const pCLDLosslessData,LOSSLESSDATA * const pICCLosslessData,const INT numOttBoxes,const INT numBands,const INT numParamSets,const INT bsIndependencyFlag)680*e5436536SAndroid Build Coastguard Worker static FDK_SACENC_ERROR writeOttData(
681*e5436536SAndroid Build Coastguard Worker HANDLE_FDK_BITSTREAM hBitstream, PREV_OTTDATA *const pPrevOttData,
682*e5436536SAndroid Build Coastguard Worker OTTDATA *const pOttData, const OTTCONFIG ottConfig[SACENC_MAX_NUM_BOXES],
683*e5436536SAndroid Build Coastguard Worker LOSSLESSDATA *const pCLDLosslessData, LOSSLESSDATA *const pICCLosslessData,
684*e5436536SAndroid Build Coastguard Worker const INT numOttBoxes, const INT numBands, const INT numParamSets,
685*e5436536SAndroid Build Coastguard Worker const INT bsIndependencyFlag) {
686*e5436536SAndroid Build Coastguard Worker FDK_SACENC_ERROR error = SACENC_OK;
687*e5436536SAndroid Build Coastguard Worker
688*e5436536SAndroid Build Coastguard Worker if ((hBitstream == NULL) || (pPrevOttData == NULL) || (pOttData == NULL) ||
689*e5436536SAndroid Build Coastguard Worker (ottConfig == NULL) || (pCLDLosslessData == NULL) ||
690*e5436536SAndroid Build Coastguard Worker (pICCLosslessData == NULL)) {
691*e5436536SAndroid Build Coastguard Worker error = SACENC_INVALID_HANDLE;
692*e5436536SAndroid Build Coastguard Worker } else {
693*e5436536SAndroid Build Coastguard Worker int i;
694*e5436536SAndroid Build Coastguard Worker for (i = 0; i < numOttBoxes; i++) {
695*e5436536SAndroid Build Coastguard Worker ecData(hBitstream, pOttData->cld[i], pPrevOttData->cld_old[i],
696*e5436536SAndroid Build Coastguard Worker pPrevOttData->quantCoarseCldPrev[i], pCLDLosslessData, t_CLD, i,
697*e5436536SAndroid Build Coastguard Worker numParamSets, bsIndependencyFlag, 0, ottConfig[i].bsOttBands, 15);
698*e5436536SAndroid Build Coastguard Worker }
699*e5436536SAndroid Build Coastguard Worker {
700*e5436536SAndroid Build Coastguard Worker for (i = 0; i < numOttBoxes; i++) {
701*e5436536SAndroid Build Coastguard Worker {
702*e5436536SAndroid Build Coastguard Worker ecData(hBitstream, pOttData->icc[i], pPrevOttData->icc_old[i],
703*e5436536SAndroid Build Coastguard Worker pPrevOttData->quantCoarseIccPrev[i], pICCLosslessData, t_ICC,
704*e5436536SAndroid Build Coastguard Worker i, numParamSets, bsIndependencyFlag, 0, numBands, 0);
705*e5436536SAndroid Build Coastguard Worker }
706*e5436536SAndroid Build Coastguard Worker } /* for i */
707*e5436536SAndroid Build Coastguard Worker }
708*e5436536SAndroid Build Coastguard Worker } /* valid handle */
709*e5436536SAndroid Build Coastguard Worker
710*e5436536SAndroid Build Coastguard Worker return error;
711*e5436536SAndroid Build Coastguard Worker }
712*e5436536SAndroid Build Coastguard Worker
713*e5436536SAndroid Build Coastguard Worker /* write extension frame data to stream */
WriteSpatialExtensionFrame(HANDLE_FDK_BITSTREAM bitstream,HANDLE_BSF_INSTANCE self)714*e5436536SAndroid Build Coastguard Worker static FDK_SACENC_ERROR WriteSpatialExtensionFrame(
715*e5436536SAndroid Build Coastguard Worker HANDLE_FDK_BITSTREAM bitstream, HANDLE_BSF_INSTANCE self) {
716*e5436536SAndroid Build Coastguard Worker FDK_SACENC_ERROR error = SACENC_OK;
717*e5436536SAndroid Build Coastguard Worker
718*e5436536SAndroid Build Coastguard Worker if ((bitstream == NULL) || (self == NULL)) {
719*e5436536SAndroid Build Coastguard Worker error = SACENC_INVALID_HANDLE;
720*e5436536SAndroid Build Coastguard Worker } else {
721*e5436536SAndroid Build Coastguard Worker FDKbyteAlign(bitstream, 0);
722*e5436536SAndroid Build Coastguard Worker } /* valid handle */
723*e5436536SAndroid Build Coastguard Worker
724*e5436536SAndroid Build Coastguard Worker return error;
725*e5436536SAndroid Build Coastguard Worker }
726*e5436536SAndroid Build Coastguard Worker
727*e5436536SAndroid Build Coastguard Worker /* write frame data to stream */
fdk_sacenc_writeSpatialFrame(UCHAR * const pOutputBuffer,const INT outputBufferSize,INT * const pnOutputBits,HANDLE_BSF_INSTANCE selfPtr)728*e5436536SAndroid Build Coastguard Worker FDK_SACENC_ERROR fdk_sacenc_writeSpatialFrame(UCHAR *const pOutputBuffer,
729*e5436536SAndroid Build Coastguard Worker const INT outputBufferSize,
730*e5436536SAndroid Build Coastguard Worker INT *const pnOutputBits,
731*e5436536SAndroid Build Coastguard Worker HANDLE_BSF_INSTANCE selfPtr) {
732*e5436536SAndroid Build Coastguard Worker FDK_SACENC_ERROR error = SACENC_OK;
733*e5436536SAndroid Build Coastguard Worker
734*e5436536SAndroid Build Coastguard Worker if ((pOutputBuffer == NULL) || (pnOutputBits == NULL) || (selfPtr == NULL)) {
735*e5436536SAndroid Build Coastguard Worker error = SACENC_INVALID_HANDLE;
736*e5436536SAndroid Build Coastguard Worker } else {
737*e5436536SAndroid Build Coastguard Worker SPATIALFRAME *frame = NULL;
738*e5436536SAndroid Build Coastguard Worker SPATIALSPECIFICCONFIG *config = NULL;
739*e5436536SAndroid Build Coastguard Worker FDK_BITSTREAM bitstream;
740*e5436536SAndroid Build Coastguard Worker
741*e5436536SAndroid Build Coastguard Worker int i, j, numParamSets, numOttBoxes;
742*e5436536SAndroid Build Coastguard Worker
743*e5436536SAndroid Build Coastguard Worker if ((NULL ==
744*e5436536SAndroid Build Coastguard Worker (frame = fdk_sacenc_getSpatialFrame(selfPtr, READ_SPATIALFRAME))) ||
745*e5436536SAndroid Build Coastguard Worker (NULL == (config = &(selfPtr->spatialSpecificConfig)))) {
746*e5436536SAndroid Build Coastguard Worker error = SACENC_INVALID_HANDLE;
747*e5436536SAndroid Build Coastguard Worker goto bail;
748*e5436536SAndroid Build Coastguard Worker }
749*e5436536SAndroid Build Coastguard Worker
750*e5436536SAndroid Build Coastguard Worker numOttBoxes = selfPtr->spatialSpecificConfig.treeDescription.numOttBoxes;
751*e5436536SAndroid Build Coastguard Worker
752*e5436536SAndroid Build Coastguard Worker numParamSets = frame->framingInfo.numParamSets;
753*e5436536SAndroid Build Coastguard Worker
754*e5436536SAndroid Build Coastguard Worker if (frame->bUseBBCues) {
755*e5436536SAndroid Build Coastguard Worker for (i = 0; i < SACENC_MAX_NUM_BOXES; i++) {
756*e5436536SAndroid Build Coastguard Worker /* If a transient was detected, force only the second ps broad band */
757*e5436536SAndroid Build Coastguard Worker if (numParamSets == 1) {
758*e5436536SAndroid Build Coastguard Worker frame->CLDLosslessData.bsFreqResStrideXXX[i][0] = 3;
759*e5436536SAndroid Build Coastguard Worker frame->ICCLosslessData.bsFreqResStrideXXX[i][0] = 3;
760*e5436536SAndroid Build Coastguard Worker } else {
761*e5436536SAndroid Build Coastguard Worker for (j = 1; j < MAX_NUM_PARAMS; j++) {
762*e5436536SAndroid Build Coastguard Worker frame->CLDLosslessData.bsFreqResStrideXXX[i][j] = 3;
763*e5436536SAndroid Build Coastguard Worker frame->ICCLosslessData.bsFreqResStrideXXX[i][j] = 3;
764*e5436536SAndroid Build Coastguard Worker }
765*e5436536SAndroid Build Coastguard Worker }
766*e5436536SAndroid Build Coastguard Worker }
767*e5436536SAndroid Build Coastguard Worker } /* frame->bUseBBCues */
768*e5436536SAndroid Build Coastguard Worker
769*e5436536SAndroid Build Coastguard Worker /* bind extern buffer to bitstream handle */
770*e5436536SAndroid Build Coastguard Worker FDKinitBitStream(&bitstream, pOutputBuffer, outputBufferSize, 0, BS_WRITER);
771*e5436536SAndroid Build Coastguard Worker
772*e5436536SAndroid Build Coastguard Worker if (SACENC_OK != (error = writeFramingInfo(
773*e5436536SAndroid Build Coastguard Worker &bitstream, &(frame->framingInfo),
774*e5436536SAndroid Build Coastguard Worker selfPtr->spatialSpecificConfig.bsFrameLength))) {
775*e5436536SAndroid Build Coastguard Worker goto bail;
776*e5436536SAndroid Build Coastguard Worker }
777*e5436536SAndroid Build Coastguard Worker
778*e5436536SAndroid Build Coastguard Worker /* write bsIndependencyFlag */
779*e5436536SAndroid Build Coastguard Worker FDKwriteBits(&bitstream, frame->bsIndependencyFlag, 1);
780*e5436536SAndroid Build Coastguard Worker
781*e5436536SAndroid Build Coastguard Worker /* write spatial data to bitstream */
782*e5436536SAndroid Build Coastguard Worker if (SACENC_OK !=
783*e5436536SAndroid Build Coastguard Worker (error = writeOttData(&bitstream, &selfPtr->prevFrameData.prevOttData,
784*e5436536SAndroid Build Coastguard Worker &frame->ottData, config->ottConfig,
785*e5436536SAndroid Build Coastguard Worker &frame->CLDLosslessData, &frame->ICCLosslessData,
786*e5436536SAndroid Build Coastguard Worker numOttBoxes, config->numBands, numParamSets,
787*e5436536SAndroid Build Coastguard Worker frame->bsIndependencyFlag))) {
788*e5436536SAndroid Build Coastguard Worker goto bail;
789*e5436536SAndroid Build Coastguard Worker }
790*e5436536SAndroid Build Coastguard Worker if (SACENC_OK != (error = writeSmgData(&bitstream, &frame->smgData,
791*e5436536SAndroid Build Coastguard Worker numParamSets, config->numBands))) {
792*e5436536SAndroid Build Coastguard Worker goto bail;
793*e5436536SAndroid Build Coastguard Worker }
794*e5436536SAndroid Build Coastguard Worker
795*e5436536SAndroid Build Coastguard Worker /* byte alignment */
796*e5436536SAndroid Build Coastguard Worker FDKbyteAlign(&bitstream, 0);
797*e5436536SAndroid Build Coastguard Worker
798*e5436536SAndroid Build Coastguard Worker /* Write SpatialExtensionFrame */
799*e5436536SAndroid Build Coastguard Worker if (SACENC_OK !=
800*e5436536SAndroid Build Coastguard Worker (error = WriteSpatialExtensionFrame(&bitstream, selfPtr))) {
801*e5436536SAndroid Build Coastguard Worker goto bail;
802*e5436536SAndroid Build Coastguard Worker }
803*e5436536SAndroid Build Coastguard Worker
804*e5436536SAndroid Build Coastguard Worker if (NULL ==
805*e5436536SAndroid Build Coastguard Worker (frame = fdk_sacenc_getSpatialFrame(selfPtr, WRITE_SPATIALFRAME))) {
806*e5436536SAndroid Build Coastguard Worker error = SACENC_INVALID_HANDLE;
807*e5436536SAndroid Build Coastguard Worker goto bail;
808*e5436536SAndroid Build Coastguard Worker }
809*e5436536SAndroid Build Coastguard Worker
810*e5436536SAndroid Build Coastguard Worker clearFrame(frame);
811*e5436536SAndroid Build Coastguard Worker
812*e5436536SAndroid Build Coastguard Worker /* return number of valid bits in bitstream */
813*e5436536SAndroid Build Coastguard Worker if ((*pnOutputBits = FDKgetValidBits(&bitstream)) >
814*e5436536SAndroid Build Coastguard Worker (outputBufferSize * 8)) {
815*e5436536SAndroid Build Coastguard Worker error = SACENC_INVALID_CONFIG;
816*e5436536SAndroid Build Coastguard Worker goto bail;
817*e5436536SAndroid Build Coastguard Worker }
818*e5436536SAndroid Build Coastguard Worker
819*e5436536SAndroid Build Coastguard Worker /* terminate buffer with alignment */
820*e5436536SAndroid Build Coastguard Worker FDKbyteAlign(&bitstream, 0);
821*e5436536SAndroid Build Coastguard Worker
822*e5436536SAndroid Build Coastguard Worker } /* valid handle */
823*e5436536SAndroid Build Coastguard Worker
824*e5436536SAndroid Build Coastguard Worker bail:
825*e5436536SAndroid Build Coastguard Worker return error;
826*e5436536SAndroid Build Coastguard Worker }
827