/src/aac/libSACenc/src/sacenc_bitstream.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* ----------------------------------------------------------------------------- |
2 | | Software License for The Fraunhofer FDK AAC Codec Library for Android |
3 | | |
4 | | © Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten |
5 | | Forschung e.V. All rights reserved. |
6 | | |
7 | | 1. INTRODUCTION |
8 | | The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software |
9 | | that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding |
10 | | scheme for digital audio. This FDK AAC Codec software is intended to be used on |
11 | | a wide variety of Android devices. |
12 | | |
13 | | AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient |
14 | | general perceptual audio codecs. AAC-ELD is considered the best-performing |
15 | | full-bandwidth communications codec by independent studies and is widely |
16 | | deployed. AAC has been standardized by ISO and IEC as part of the MPEG |
17 | | specifications. |
18 | | |
19 | | Patent licenses for necessary patent claims for the FDK AAC Codec (including |
20 | | those of Fraunhofer) may be obtained through Via Licensing |
21 | | (www.vialicensing.com) or through the respective patent owners individually for |
22 | | the purpose of encoding or decoding bit streams in products that are compliant |
23 | | with the ISO/IEC MPEG audio standards. Please note that most manufacturers of |
24 | | Android devices already license these patent claims through Via Licensing or |
25 | | directly from the patent owners, and therefore FDK AAC Codec software may |
26 | | already be covered under those patent licenses when it is used for those |
27 | | licensed purposes only. |
28 | | |
29 | | Commercially-licensed AAC software libraries, including floating-point versions |
30 | | with enhanced sound quality, are also available from Fraunhofer. Users are |
31 | | encouraged to check the Fraunhofer website for additional applications |
32 | | information and documentation. |
33 | | |
34 | | 2. COPYRIGHT LICENSE |
35 | | |
36 | | Redistribution and use in source and binary forms, with or without modification, |
37 | | are permitted without payment of copyright license fees provided that you |
38 | | satisfy the following conditions: |
39 | | |
40 | | You must retain the complete text of this software license in redistributions of |
41 | | the FDK AAC Codec or your modifications thereto in source code form. |
42 | | |
43 | | You must retain the complete text of this software license in the documentation |
44 | | and/or other materials provided with redistributions of the FDK AAC Codec or |
45 | | your modifications thereto in binary form. You must make available free of |
46 | | charge copies of the complete source code of the FDK AAC Codec and your |
47 | | modifications thereto to recipients of copies in binary form. |
48 | | |
49 | | The name of Fraunhofer may not be used to endorse or promote products derived |
50 | | from this library without prior written permission. |
51 | | |
52 | | You may not charge copyright license fees for anyone to use, copy or distribute |
53 | | the FDK AAC Codec software or your modifications thereto. |
54 | | |
55 | | Your modified versions of the FDK AAC Codec must carry prominent notices stating |
56 | | that you changed the software and the date of any change. For modified versions |
57 | | of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" |
58 | | must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK |
59 | | AAC Codec Library for Android." |
60 | | |
61 | | 3. NO PATENT LICENSE |
62 | | |
63 | | NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without |
64 | | limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. |
65 | | Fraunhofer provides no warranty of patent non-infringement with respect to this |
66 | | software. |
67 | | |
68 | | You may use this FDK AAC Codec software or modifications thereto only for |
69 | | purposes that are authorized by appropriate patent licenses. |
70 | | |
71 | | 4. DISCLAIMER |
72 | | |
73 | | This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright |
74 | | holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, |
75 | | including but not limited to the implied warranties of merchantability and |
76 | | fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR |
77 | | CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, |
78 | | or consequential damages, including but not limited to procurement of substitute |
79 | | goods or services; loss of use, data, or profits, or business interruption, |
80 | | however caused and on any theory of liability, whether in contract, strict |
81 | | liability, or tort (including negligence), arising in any way out of the use of |
82 | | this software, even if advised of the possibility of such damage. |
83 | | |
84 | | 5. CONTACT INFORMATION |
85 | | |
86 | | Fraunhofer Institute for Integrated Circuits IIS |
87 | | Attention: Audio and Multimedia Departments - FDK AAC LL |
88 | | Am Wolfsmantel 33 |
89 | | 91058 Erlangen, Germany |
90 | | |
91 | | www.iis.fraunhofer.de/amm |
92 | | amm-info@iis.fraunhofer.de |
93 | | ----------------------------------------------------------------------------- */ |
94 | | |
95 | | /*********************** MPEG surround encoder library ************************* |
96 | | |
97 | | Author(s): |
98 | | |
99 | | Description: Encoder Library Interface |
100 | | Bitstream Writer |
101 | | |
102 | | *******************************************************************************/ |
103 | | |
104 | | /* Includes ******************************************************************/ |
105 | | #include "sacenc_bitstream.h" |
106 | | #include "sacenc_const.h" |
107 | | |
108 | | #include "genericStds.h" |
109 | | #include "common_fix.h" |
110 | | |
111 | | #include "FDK_matrixCalloc.h" |
112 | | #include "sacenc_nlc_enc.h" |
113 | | |
114 | | /* Defines *******************************************************************/ |
115 | 0 | #define MAX_FREQ_RES_INDEX 8 |
116 | 0 | #define MAX_SAMPLING_FREQUENCY_INDEX 13 |
117 | 0 | #define SAMPLING_FREQUENCY_INDEX_ESCAPE 15 |
118 | | |
119 | | /* Data Types ****************************************************************/ |
120 | | typedef struct { |
121 | | SCHAR cld_old[SACENC_MAX_NUM_BOXES][MAX_NUM_BINS]; |
122 | | SCHAR icc_old[SACENC_MAX_NUM_BOXES][MAX_NUM_BINS]; |
123 | | UCHAR quantCoarseCldPrev[SACENC_MAX_NUM_BOXES][MAX_NUM_PARAMS]; |
124 | | UCHAR quantCoarseIccPrev[SACENC_MAX_NUM_BOXES][MAX_NUM_PARAMS]; |
125 | | |
126 | | } PREV_OTTDATA; |
127 | | |
128 | | typedef struct { |
129 | | PREV_OTTDATA prevOttData; |
130 | | |
131 | | } STATIC_SPATIALFRAME; |
132 | | |
133 | | typedef struct BSF_INSTANCE { |
134 | | SPATIALSPECIFICCONFIG spatialSpecificConfig; |
135 | | SPATIALFRAME frame; |
136 | | STATIC_SPATIALFRAME prevFrameData; |
137 | | |
138 | | } BSF_INSTANCE; |
139 | | |
140 | | /* Constants *****************************************************************/ |
141 | | static const INT SampleRateTable[MAX_SAMPLING_FREQUENCY_INDEX] = { |
142 | | 96000, 88200, 64000, 48000, 44100, 32000, 24000, |
143 | | 22050, 16000, 12000, 11025, 8000, 7350}; |
144 | | |
145 | | static const UCHAR FreqResBinTable_LD[MAX_FREQ_RES_INDEX] = {0, 23, 15, 12, |
146 | | 9, 7, 5, 4}; |
147 | | static const UCHAR FreqResStrideTable_LD[] = {1, 2, 5, 23}; |
148 | | |
149 | | /* Function / Class Declarations *********************************************/ |
150 | | |
151 | | /* Function / Class Definition ***********************************************/ |
152 | | static FDK_SACENC_ERROR DuplicateLosslessData( |
153 | | const INT startBox, const INT stopBox, |
154 | | const LOSSLESSDATA *const hLosslessDataFrom, const INT setFrom, |
155 | 0 | LOSSLESSDATA *const hLosslessDataTo, const INT setTo) { |
156 | 0 | FDK_SACENC_ERROR error = SACENC_OK; |
157 | |
|
158 | 0 | if ((NULL == hLosslessDataFrom) || (NULL == hLosslessDataTo)) { |
159 | 0 | error = SACENC_INVALID_HANDLE; |
160 | 0 | } else { |
161 | 0 | int i; |
162 | |
|
163 | 0 | for (i = startBox; i < stopBox; i++) { |
164 | 0 | hLosslessDataTo->bsXXXDataMode[i][setTo] = |
165 | 0 | hLosslessDataFrom->bsXXXDataMode[i][setFrom]; |
166 | 0 | hLosslessDataTo->bsDataPair[i][setTo] = |
167 | 0 | hLosslessDataFrom->bsDataPair[i][setFrom]; |
168 | 0 | hLosslessDataTo->bsQuantCoarseXXX[i][setTo] = |
169 | 0 | hLosslessDataFrom->bsQuantCoarseXXX[i][setFrom]; |
170 | 0 | hLosslessDataTo->bsFreqResStrideXXX[i][setTo] = |
171 | 0 | hLosslessDataFrom->bsFreqResStrideXXX[i][setFrom]; |
172 | 0 | } |
173 | 0 | } |
174 | 0 | return error; |
175 | 0 | } |
176 | | |
177 | | FDK_SACENC_ERROR fdk_sacenc_duplicateParameterSet( |
178 | | const SPATIALFRAME *const hFrom, const INT setFrom, SPATIALFRAME *const hTo, |
179 | 0 | const INT setTo) { |
180 | 0 | FDK_SACENC_ERROR error = SACENC_OK; |
181 | |
|
182 | 0 | if ((NULL == hFrom) || (NULL == hTo)) { |
183 | 0 | error = SACENC_INVALID_HANDLE; |
184 | 0 | } else { |
185 | 0 | int box; |
186 | | /* Only Copy Parameter Set selective stuff */ |
187 | | |
188 | | /* OTT-Data */ |
189 | 0 | for (box = 0; box < SACENC_MAX_NUM_BOXES; box++) { |
190 | 0 | FDKmemcpy(hTo->ottData.cld[box][setTo], hFrom->ottData.cld[box][setFrom], |
191 | 0 | sizeof(hFrom->ottData.cld[0][0])); |
192 | 0 | FDKmemcpy(hTo->ottData.icc[box][setTo], hFrom->ottData.icc[box][setFrom], |
193 | 0 | sizeof(hFrom->ottData.icc[0][0])); |
194 | 0 | } |
195 | | |
196 | | /* LOSSLESSDATA */ |
197 | 0 | DuplicateLosslessData(0, SACENC_MAX_NUM_BOXES, &hFrom->CLDLosslessData, |
198 | 0 | setFrom, &hTo->CLDLosslessData, setTo); |
199 | 0 | DuplicateLosslessData(0, SACENC_MAX_NUM_BOXES, &hFrom->ICCLosslessData, |
200 | 0 | setFrom, &hTo->ICCLosslessData, setTo); |
201 | |
|
202 | 0 | } /* valid handle */ |
203 | |
|
204 | 0 | return error; |
205 | 0 | } |
206 | | |
207 | | /* set frame defaults */ |
208 | 0 | static void clearFrame(SPATIALFRAME *const pFrame) { |
209 | 0 | FDKmemclear(pFrame, sizeof(SPATIALFRAME)); |
210 | |
|
211 | 0 | pFrame->bsIndependencyFlag = 1; |
212 | 0 | pFrame->framingInfo.numParamSets = 1; |
213 | 0 | } |
214 | | |
215 | | static void fine2coarse(SCHAR *const data, const DATA_TYPE dataType, |
216 | 0 | const INT startBand, const INT numBands) { |
217 | 0 | int i; |
218 | 0 | if (dataType == t_CLD) { |
219 | 0 | for (i = startBand; i < startBand + numBands; i++) { |
220 | 0 | data[i] /= 2; |
221 | 0 | } |
222 | 0 | } else { |
223 | 0 | for (i = startBand; i < startBand + numBands; i++) { |
224 | 0 | data[i] >>= 1; |
225 | 0 | } |
226 | 0 | } |
227 | 0 | } |
228 | | |
229 | | static void coarse2fine(SCHAR *const data, const DATA_TYPE dataType, |
230 | 0 | const INT startBand, const INT numBands) { |
231 | 0 | int i; |
232 | |
|
233 | 0 | for (i = startBand; i < startBand + numBands; i++) { |
234 | 0 | data[i] <<= 1; |
235 | 0 | } |
236 | |
|
237 | 0 | if (dataType == t_CLD) { |
238 | 0 | for (i = startBand; i < startBand + numBands; i++) { |
239 | 0 | if (data[i] == -14) { |
240 | 0 | data[i] = -15; |
241 | 0 | } else if (data[i] == 14) { |
242 | 0 | data[i] = 15; |
243 | 0 | } |
244 | 0 | } |
245 | 0 | } /* (dataType == t_CLD) */ |
246 | 0 | } |
247 | | |
248 | 0 | static UCHAR getBsFreqResStride(const INT index) { |
249 | 0 | const UCHAR *pFreqResStrideTable = NULL; |
250 | 0 | int freqResStrideTableSize = 0; |
251 | |
|
252 | 0 | pFreqResStrideTable = FreqResStrideTable_LD; |
253 | 0 | freqResStrideTableSize = |
254 | 0 | sizeof(FreqResStrideTable_LD) / sizeof(*FreqResStrideTable_LD); |
255 | |
|
256 | 0 | return (((NULL != pFreqResStrideTable) && (index >= 0) && |
257 | 0 | (index < freqResStrideTableSize)) |
258 | 0 | ? pFreqResStrideTable[index] |
259 | 0 | : 1); |
260 | 0 | } |
261 | | |
262 | | /* write data to bitstream */ |
263 | | static void ecData(HANDLE_FDK_BITSTREAM bitstream, |
264 | | SCHAR data[MAX_NUM_PARAMS][MAX_NUM_BINS], |
265 | | SCHAR oldData[MAX_NUM_BINS], |
266 | | UCHAR quantCoarseXXXprev[MAX_NUM_PARAMS], |
267 | | LOSSLESSDATA *const losslessData, const DATA_TYPE dataType, |
268 | | const INT paramIdx, const INT numParamSets, |
269 | | const INT independencyFlag, const INT startBand, |
270 | 0 | const INT stopBand, const INT defaultValue) { |
271 | 0 | int ps, pb, strOffset, pbStride, dataBands, i; |
272 | 0 | int aStrides[MAX_NUM_BINS + 1] = {0}; |
273 | 0 | SHORT cmpIdxData[2][MAX_NUM_BINS] = {{0}}; |
274 | 0 | SHORT cmpOldData[MAX_NUM_BINS] = {0}; |
275 | | |
276 | | /* bsXXXDataMode */ |
277 | 0 | if (independencyFlag || (losslessData->bsQuantCoarseXXX[paramIdx][0] != |
278 | 0 | quantCoarseXXXprev[paramIdx])) { |
279 | 0 | losslessData->bsXXXDataMode[paramIdx][0] = FINECOARSE; |
280 | 0 | } else { |
281 | 0 | losslessData->bsXXXDataMode[paramIdx][0] = KEEP; |
282 | 0 | for (i = startBand; i < stopBand; i++) { |
283 | 0 | if (data[0][i] != oldData[i]) { |
284 | 0 | losslessData->bsXXXDataMode[paramIdx][0] = FINECOARSE; |
285 | 0 | break; |
286 | 0 | } |
287 | 0 | } |
288 | 0 | } |
289 | |
|
290 | 0 | FDKwriteBits(bitstream, losslessData->bsXXXDataMode[paramIdx][0], 2); |
291 | |
|
292 | 0 | for (ps = 1; ps < numParamSets; ps++) { |
293 | 0 | if (losslessData->bsQuantCoarseXXX[paramIdx][ps] != |
294 | 0 | losslessData->bsQuantCoarseXXX[paramIdx][ps - 1]) { |
295 | 0 | losslessData->bsXXXDataMode[paramIdx][ps] = FINECOARSE; |
296 | 0 | } else { |
297 | 0 | losslessData->bsXXXDataMode[paramIdx][ps] = KEEP; |
298 | 0 | for (i = startBand; i < stopBand; i++) { |
299 | 0 | if (data[ps][i] != data[ps - 1][i]) { |
300 | 0 | losslessData->bsXXXDataMode[paramIdx][ps] = FINECOARSE; |
301 | 0 | break; |
302 | 0 | } |
303 | 0 | } |
304 | 0 | } |
305 | |
|
306 | 0 | FDKwriteBits(bitstream, losslessData->bsXXXDataMode[paramIdx][ps], 2); |
307 | 0 | } /* for ps */ |
308 | | |
309 | | /* Create data pairs if possible */ |
310 | 0 | for (ps = 0; ps < (numParamSets - 1); ps++) { |
311 | 0 | if (losslessData->bsXXXDataMode[paramIdx][ps] == FINECOARSE) { |
312 | | /* Check if next parameter set is FINCOARSE */ |
313 | 0 | if (losslessData->bsXXXDataMode[paramIdx][ps + 1] == FINECOARSE) { |
314 | | /* We have to check if ps and ps+1 use the same bsXXXQuantMode */ |
315 | | /* and also have the same stride */ |
316 | 0 | if ((losslessData->bsQuantCoarseXXX[paramIdx][ps + 1] == |
317 | 0 | losslessData->bsQuantCoarseXXX[paramIdx][ps]) && |
318 | 0 | (losslessData->bsFreqResStrideXXX[paramIdx][ps + 1] == |
319 | 0 | losslessData->bsFreqResStrideXXX[paramIdx][ps])) { |
320 | 0 | losslessData->bsDataPair[paramIdx][ps] = 1; |
321 | 0 | losslessData->bsDataPair[paramIdx][ps + 1] = 1; |
322 | | |
323 | | /* We have a data pair -> Jump to the ps after next ps*/ |
324 | 0 | ps++; |
325 | 0 | continue; |
326 | 0 | } |
327 | 0 | } |
328 | | /* dataMode of next ps is not FINECOARSE or does not use the same |
329 | | * bsXXXQuantMode/stride */ |
330 | | /* -> no dataPair possible */ |
331 | 0 | losslessData->bsDataPair[paramIdx][ps] = 0; |
332 | | |
333 | | /* Initialize ps after next ps to Zero (only important for the last |
334 | | * parameter set) */ |
335 | 0 | losslessData->bsDataPair[paramIdx][ps + 1] = 0; |
336 | 0 | } else { |
337 | | /* No FINECOARSE -> no data pair possible */ |
338 | 0 | losslessData->bsDataPair[paramIdx][ps] = 0; |
339 | | |
340 | | /* Initialize ps after next ps to Zero (only important for the last |
341 | | * parameter set) */ |
342 | 0 | losslessData->bsDataPair[paramIdx][ps + 1] = 0; |
343 | 0 | } |
344 | 0 | } /* for ps */ |
345 | |
|
346 | 0 | for (ps = 0; ps < numParamSets; ps++) { |
347 | 0 | if (losslessData->bsXXXDataMode[paramIdx][ps] == DEFAULT) { |
348 | | /* Prepare old data */ |
349 | 0 | for (i = startBand; i < stopBand; i++) { |
350 | 0 | oldData[i] = defaultValue; |
351 | 0 | } |
352 | 0 | quantCoarseXXXprev[paramIdx] = 0; /* Default data are always fine */ |
353 | 0 | } |
354 | |
|
355 | 0 | if (losslessData->bsXXXDataMode[paramIdx][ps] == FINECOARSE) { |
356 | 0 | FDKwriteBits(bitstream, losslessData->bsDataPair[paramIdx][ps], 1); |
357 | 0 | FDKwriteBits(bitstream, losslessData->bsQuantCoarseXXX[paramIdx][ps], 1); |
358 | 0 | FDKwriteBits(bitstream, losslessData->bsFreqResStrideXXX[paramIdx][ps], |
359 | 0 | 2); |
360 | |
|
361 | 0 | if (losslessData->bsQuantCoarseXXX[paramIdx][ps] != |
362 | 0 | quantCoarseXXXprev[paramIdx]) { |
363 | 0 | if (quantCoarseXXXprev[paramIdx]) { |
364 | 0 | coarse2fine(oldData, dataType, startBand, stopBand - startBand); |
365 | 0 | } else { |
366 | 0 | fine2coarse(oldData, dataType, startBand, stopBand - startBand); |
367 | 0 | } |
368 | 0 | } |
369 | | |
370 | | /* Handle strides */ |
371 | 0 | pbStride = |
372 | 0 | getBsFreqResStride(losslessData->bsFreqResStrideXXX[paramIdx][ps]); |
373 | 0 | dataBands = (stopBand - startBand - 1) / pbStride + 1; |
374 | |
|
375 | 0 | aStrides[0] = startBand; |
376 | 0 | for (pb = 1; pb <= dataBands; pb++) { |
377 | 0 | aStrides[pb] = aStrides[pb - 1] + pbStride; |
378 | 0 | } |
379 | |
|
380 | 0 | strOffset = 0; |
381 | 0 | while (aStrides[dataBands] > stopBand) { |
382 | 0 | if (strOffset < dataBands) { |
383 | 0 | strOffset++; |
384 | 0 | } |
385 | 0 | for (i = strOffset; i <= dataBands; i++) { |
386 | 0 | aStrides[i]--; |
387 | 0 | } |
388 | 0 | } /* while */ |
389 | |
|
390 | 0 | for (pb = 0; pb < dataBands; pb++) { |
391 | 0 | cmpOldData[startBand + pb] = oldData[aStrides[pb]]; |
392 | 0 | cmpIdxData[0][startBand + pb] = data[ps][aStrides[pb]]; |
393 | |
|
394 | 0 | if (losslessData->bsDataPair[paramIdx][ps]) { |
395 | 0 | cmpIdxData[1][startBand + pb] = data[ps + 1][aStrides[pb]]; |
396 | 0 | } |
397 | 0 | } /* for pb*/ |
398 | | |
399 | | /* Finally encode */ |
400 | 0 | if (losslessData->bsDataPair[paramIdx][ps]) { |
401 | 0 | fdk_sacenc_ecDataPairEnc(bitstream, cmpIdxData, cmpOldData, dataType, 0, |
402 | 0 | startBand, dataBands, |
403 | 0 | losslessData->bsQuantCoarseXXX[paramIdx][ps], |
404 | 0 | independencyFlag && (ps == 0)); |
405 | 0 | } else { |
406 | 0 | fdk_sacenc_ecDataSingleEnc(bitstream, cmpIdxData, cmpOldData, dataType, |
407 | 0 | 0, startBand, dataBands, |
408 | 0 | losslessData->bsQuantCoarseXXX[paramIdx][ps], |
409 | 0 | independencyFlag && (ps == 0)); |
410 | 0 | } |
411 | | |
412 | | /* Overwrite old data */ |
413 | 0 | for (i = startBand; i < stopBand; i++) { |
414 | 0 | if (losslessData->bsDataPair[paramIdx][ps]) { |
415 | 0 | oldData[i] = data[ps + 1][i]; |
416 | 0 | } else { |
417 | 0 | oldData[i] = data[ps][i]; |
418 | 0 | } |
419 | 0 | } |
420 | |
|
421 | 0 | quantCoarseXXXprev[paramIdx] = |
422 | 0 | losslessData->bsQuantCoarseXXX[paramIdx][ps]; |
423 | | |
424 | | /* Jump forward if we have encoded a data pair */ |
425 | 0 | if (losslessData->bsDataPair[paramIdx][ps]) { |
426 | 0 | ps++; |
427 | 0 | } |
428 | |
|
429 | 0 | } /* if (losslessData->bsXXXDataMode[paramIdx][ps] == FINECOARSE ) */ |
430 | 0 | } /* for ps */ |
431 | 0 | } |
432 | | |
433 | | /****************************************************************************/ |
434 | | /* Bitstream formatter interface functions */ |
435 | | /****************************************************************************/ |
436 | | static FDK_SACENC_ERROR getBsFreqResIndex(const INT numBands, |
437 | 0 | INT *const pbsFreqResIndex) { |
438 | 0 | FDK_SACENC_ERROR error = SACENC_OK; |
439 | |
|
440 | 0 | if (NULL == pbsFreqResIndex) { |
441 | 0 | error = SACENC_INVALID_HANDLE; |
442 | 0 | } else { |
443 | 0 | const UCHAR *pFreqResBinTable = FreqResBinTable_LD; |
444 | 0 | int i; |
445 | 0 | *pbsFreqResIndex = -1; |
446 | |
|
447 | 0 | for (i = 0; i < MAX_FREQ_RES_INDEX; i++) { |
448 | 0 | if (numBands == pFreqResBinTable[i]) { |
449 | 0 | *pbsFreqResIndex = i; |
450 | 0 | break; |
451 | 0 | } |
452 | 0 | } |
453 | 0 | if (*pbsFreqResIndex < 0 || *pbsFreqResIndex >= MAX_FREQ_RES_INDEX) { |
454 | 0 | error = SACENC_INVALID_CONFIG; |
455 | 0 | } |
456 | 0 | } |
457 | 0 | return error; |
458 | 0 | } |
459 | | |
460 | | static FDK_SACENC_ERROR getSamplingFrequencyIndex( |
461 | 0 | const INT bsSamplingFrequency, INT *const pbsSamplingFrequencyIndex) { |
462 | 0 | FDK_SACENC_ERROR error = SACENC_OK; |
463 | |
|
464 | 0 | if (NULL == pbsSamplingFrequencyIndex) { |
465 | 0 | error = SACENC_INVALID_HANDLE; |
466 | 0 | } else { |
467 | 0 | int i; |
468 | 0 | *pbsSamplingFrequencyIndex = SAMPLING_FREQUENCY_INDEX_ESCAPE; |
469 | |
|
470 | 0 | for (i = 0; i < MAX_SAMPLING_FREQUENCY_INDEX; i++) { |
471 | 0 | if (bsSamplingFrequency == SampleRateTable[i]) { /*spatial sampling rate*/ |
472 | 0 | *pbsSamplingFrequencyIndex = i; |
473 | 0 | break; |
474 | 0 | } |
475 | 0 | } |
476 | 0 | } |
477 | 0 | return error; |
478 | 0 | } |
479 | | |
480 | | /* destroy encoder instance */ |
481 | | FDK_SACENC_ERROR fdk_sacenc_destroySpatialBitstreamEncoder( |
482 | 0 | HANDLE_BSF_INSTANCE *selfPtr) { |
483 | 0 | FDK_SACENC_ERROR error = SACENC_OK; |
484 | |
|
485 | 0 | if ((selfPtr == NULL) || (*selfPtr == NULL)) { |
486 | 0 | error = SACENC_INVALID_HANDLE; |
487 | 0 | } else { |
488 | 0 | if (*selfPtr != NULL) { |
489 | 0 | FDK_FREE_MEMORY_1D(*selfPtr); |
490 | 0 | } |
491 | 0 | } |
492 | 0 | return error; |
493 | 0 | } |
494 | | |
495 | | /* create encoder instance */ |
496 | | FDK_SACENC_ERROR fdk_sacenc_createSpatialBitstreamEncoder( |
497 | 0 | HANDLE_BSF_INSTANCE *selfPtr) { |
498 | 0 | FDK_SACENC_ERROR error = SACENC_OK; |
499 | |
|
500 | 0 | if (NULL == selfPtr) { |
501 | 0 | error = SACENC_INVALID_HANDLE; |
502 | 0 | } else { |
503 | | /* allocate encoder struct */ |
504 | 0 | FDK_ALLOCATE_MEMORY_1D(*selfPtr, 1, BSF_INSTANCE); |
505 | 0 | } |
506 | 0 | return error; |
507 | | |
508 | 0 | bail: |
509 | 0 | fdk_sacenc_destroySpatialBitstreamEncoder(selfPtr); |
510 | 0 | return ((SACENC_OK == error) ? SACENC_MEMORY_ERROR : error); |
511 | 0 | } |
512 | | |
513 | | /* init encoder instance */ |
514 | | FDK_SACENC_ERROR fdk_sacenc_initSpatialBitstreamEncoder( |
515 | 0 | HANDLE_BSF_INSTANCE selfPtr) { |
516 | 0 | FDK_SACENC_ERROR error = SACENC_OK; |
517 | |
|
518 | 0 | if (selfPtr == NULL) { |
519 | 0 | error = SACENC_INVALID_HANDLE; |
520 | 0 | } else { |
521 | | /* init/clear */ |
522 | 0 | clearFrame(&selfPtr->frame); |
523 | |
|
524 | 0 | } /* valid handle */ |
525 | 0 | return error; |
526 | 0 | } |
527 | | |
528 | | /* get SpatialSpecificConfig struct */ |
529 | | SPATIALSPECIFICCONFIG *fdk_sacenc_getSpatialSpecificConfig( |
530 | 0 | HANDLE_BSF_INSTANCE selfPtr) { |
531 | 0 | return ((selfPtr == NULL) ? NULL : &(selfPtr->spatialSpecificConfig)); |
532 | 0 | } |
533 | | |
534 | | /* write SpatialSpecificConfig to stream */ |
535 | | FDK_SACENC_ERROR fdk_sacenc_writeSpatialSpecificConfig( |
536 | | SPATIALSPECIFICCONFIG *const spatialSpecificConfig, |
537 | | UCHAR *const pOutputBuffer, const INT outputBufferSize, |
538 | 0 | INT *const pnOutputBits) { |
539 | 0 | FDK_SACENC_ERROR error = SACENC_OK; |
540 | 0 | INT bsSamplingFrequencyIndex = 0; |
541 | 0 | INT bsFreqRes = 0; |
542 | |
|
543 | 0 | if ((spatialSpecificConfig == NULL) || (pOutputBuffer == NULL) || |
544 | 0 | (pnOutputBits == NULL)) { |
545 | 0 | error = SACENC_INVALID_HANDLE; |
546 | 0 | } else { |
547 | 0 | FDK_BITSTREAM bitstream; |
548 | | |
549 | | /* Find FreqRes */ |
550 | 0 | if (SACENC_OK != (error = getBsFreqResIndex(spatialSpecificConfig->numBands, |
551 | 0 | &bsFreqRes))) |
552 | 0 | goto bail; |
553 | | |
554 | | /* Find SamplingFrequencyIndex */ |
555 | 0 | if (SACENC_OK != (error = getSamplingFrequencyIndex( |
556 | 0 | spatialSpecificConfig->bsSamplingFrequency, |
557 | 0 | &bsSamplingFrequencyIndex))) |
558 | 0 | goto bail; |
559 | | |
560 | | /* bind extern buffer to bitstream handle */ |
561 | 0 | FDKinitBitStream(&bitstream, pOutputBuffer, outputBufferSize, 0, BS_WRITER); |
562 | | |
563 | | /****************************************************************************/ |
564 | | /* write to bitstream */ |
565 | |
|
566 | 0 | FDKwriteBits(&bitstream, bsSamplingFrequencyIndex, 4); |
567 | |
|
568 | 0 | if (bsSamplingFrequencyIndex == 15) { |
569 | 0 | FDKwriteBits(&bitstream, spatialSpecificConfig->bsSamplingFrequency, 24); |
570 | 0 | } |
571 | |
|
572 | 0 | FDKwriteBits(&bitstream, spatialSpecificConfig->bsFrameLength, 5); |
573 | |
|
574 | 0 | FDKwriteBits(&bitstream, bsFreqRes, 3); |
575 | 0 | FDKwriteBits(&bitstream, spatialSpecificConfig->bsTreeConfig, 4); |
576 | 0 | FDKwriteBits(&bitstream, spatialSpecificConfig->bsQuantMode, 2); |
577 | |
|
578 | 0 | FDKwriteBits(&bitstream, 0, 1); /* bsArbitraryDownmix */ |
579 | |
|
580 | 0 | FDKwriteBits(&bitstream, spatialSpecificConfig->bsFixedGainDMX, 3); |
581 | |
|
582 | 0 | FDKwriteBits(&bitstream, TEMPSHAPE_OFF, 2); |
583 | 0 | FDKwriteBits(&bitstream, spatialSpecificConfig->bsDecorrConfig, 2); |
584 | |
|
585 | 0 | FDKbyteAlign(&bitstream, 0); /* byte alignment */ |
586 | | |
587 | | /* return number of valid bits in bitstream */ |
588 | 0 | if ((*pnOutputBits = FDKgetValidBits(&bitstream)) > |
589 | 0 | (outputBufferSize * 8)) { |
590 | 0 | error = SACENC_INVALID_CONFIG; |
591 | 0 | goto bail; |
592 | 0 | } |
593 | | |
594 | | /* terminate buffer with alignment */ |
595 | 0 | FDKbyteAlign(&bitstream, 0); |
596 | |
|
597 | 0 | } /* valid handle */ |
598 | | |
599 | 0 | bail: |
600 | 0 | return error; |
601 | 0 | } |
602 | | |
603 | | /* get SpatialFrame struct */ |
604 | | SPATIALFRAME *fdk_sacenc_getSpatialFrame(HANDLE_BSF_INSTANCE selfPtr, |
605 | 0 | const SPATIALFRAME_TYPE frameType) { |
606 | 0 | int idx = -1; |
607 | |
|
608 | 0 | switch (frameType) { |
609 | 0 | case READ_SPATIALFRAME: |
610 | 0 | case WRITE_SPATIALFRAME: |
611 | 0 | idx = 0; |
612 | 0 | break; |
613 | 0 | default: |
614 | 0 | idx = -1; /* invalid configuration */ |
615 | 0 | } /* switch frameType */ |
616 | | |
617 | 0 | return (((selfPtr == NULL) || (idx == -1)) ? NULL : &selfPtr->frame); |
618 | 0 | } |
619 | | |
620 | | static FDK_SACENC_ERROR writeFramingInfo(HANDLE_FDK_BITSTREAM hBitstream, |
621 | | const FRAMINGINFO *const pFramingInfo, |
622 | 0 | const INT frameLength) { |
623 | 0 | FDK_SACENC_ERROR error = SACENC_OK; |
624 | |
|
625 | 0 | if ((hBitstream == NULL) || (pFramingInfo == NULL)) { |
626 | 0 | error = SACENC_INVALID_HANDLE; |
627 | 0 | } else { |
628 | 0 | FDKwriteBits(hBitstream, pFramingInfo->bsFramingType, 1); |
629 | 0 | FDKwriteBits(hBitstream, pFramingInfo->numParamSets - 1, 1); |
630 | |
|
631 | 0 | if (pFramingInfo->bsFramingType) { |
632 | 0 | int ps = 0; |
633 | 0 | int numParamSets = pFramingInfo->numParamSets; |
634 | |
|
635 | 0 | { |
636 | 0 | for (ps = 0; ps < numParamSets; ps++) { |
637 | 0 | int bitsParamSlot = 0; |
638 | 0 | while ((1 << bitsParamSlot) < (frameLength + 1)) bitsParamSlot++; |
639 | 0 | if (bitsParamSlot > 0) |
640 | 0 | FDKwriteBits(hBitstream, pFramingInfo->bsParamSlots[ps], |
641 | 0 | bitsParamSlot); |
642 | 0 | } |
643 | 0 | } |
644 | 0 | } /* pFramingInfo->bsFramingType */ |
645 | 0 | } /* valid handle */ |
646 | |
|
647 | 0 | return error; |
648 | 0 | } |
649 | | |
650 | | static FDK_SACENC_ERROR writeSmgData(HANDLE_FDK_BITSTREAM hBitstream, |
651 | | const SMGDATA *const pSmgData, |
652 | | const INT numParamSets, |
653 | 0 | const INT dataBands) { |
654 | 0 | FDK_SACENC_ERROR error = SACENC_OK; |
655 | |
|
656 | 0 | if ((hBitstream == NULL) || (pSmgData == NULL)) { |
657 | 0 | error = SACENC_INVALID_HANDLE; |
658 | 0 | } else { |
659 | 0 | int i, j; |
660 | |
|
661 | 0 | for (i = 0; i < numParamSets; i++) { |
662 | 0 | FDKwriteBits(hBitstream, pSmgData->bsSmoothMode[i], 2); |
663 | |
|
664 | 0 | if (pSmgData->bsSmoothMode[i] >= 2) { |
665 | 0 | FDKwriteBits(hBitstream, pSmgData->bsSmoothTime[i], 2); |
666 | 0 | } |
667 | 0 | if (pSmgData->bsSmoothMode[i] == 3) { |
668 | 0 | const int stride = getBsFreqResStride(pSmgData->bsFreqResStride[i]); |
669 | 0 | FDKwriteBits(hBitstream, pSmgData->bsFreqResStride[i], 2); |
670 | 0 | for (j = 0; j < dataBands; j += stride) { |
671 | 0 | FDKwriteBits(hBitstream, pSmgData->bsSmgData[i][j], 1); |
672 | 0 | } |
673 | 0 | } |
674 | 0 | } /* for i */ |
675 | 0 | } /* valid handle */ |
676 | |
|
677 | 0 | return error; |
678 | 0 | } |
679 | | |
680 | | static FDK_SACENC_ERROR writeOttData( |
681 | | HANDLE_FDK_BITSTREAM hBitstream, PREV_OTTDATA *const pPrevOttData, |
682 | | OTTDATA *const pOttData, const OTTCONFIG ottConfig[SACENC_MAX_NUM_BOXES], |
683 | | LOSSLESSDATA *const pCLDLosslessData, LOSSLESSDATA *const pICCLosslessData, |
684 | | const INT numOttBoxes, const INT numBands, const INT numParamSets, |
685 | 0 | const INT bsIndependencyFlag) { |
686 | 0 | FDK_SACENC_ERROR error = SACENC_OK; |
687 | |
|
688 | 0 | if ((hBitstream == NULL) || (pPrevOttData == NULL) || (pOttData == NULL) || |
689 | 0 | (ottConfig == NULL) || (pCLDLosslessData == NULL) || |
690 | 0 | (pICCLosslessData == NULL)) { |
691 | 0 | error = SACENC_INVALID_HANDLE; |
692 | 0 | } else { |
693 | 0 | int i; |
694 | 0 | for (i = 0; i < numOttBoxes; i++) { |
695 | 0 | ecData(hBitstream, pOttData->cld[i], pPrevOttData->cld_old[i], |
696 | 0 | pPrevOttData->quantCoarseCldPrev[i], pCLDLosslessData, t_CLD, i, |
697 | 0 | numParamSets, bsIndependencyFlag, 0, ottConfig[i].bsOttBands, 15); |
698 | 0 | } |
699 | 0 | { |
700 | 0 | for (i = 0; i < numOttBoxes; i++) { |
701 | 0 | { |
702 | 0 | ecData(hBitstream, pOttData->icc[i], pPrevOttData->icc_old[i], |
703 | 0 | pPrevOttData->quantCoarseIccPrev[i], pICCLosslessData, t_ICC, |
704 | 0 | i, numParamSets, bsIndependencyFlag, 0, numBands, 0); |
705 | 0 | } |
706 | 0 | } /* for i */ |
707 | 0 | } |
708 | 0 | } /* valid handle */ |
709 | |
|
710 | 0 | return error; |
711 | 0 | } |
712 | | |
713 | | /* write extension frame data to stream */ |
714 | | static FDK_SACENC_ERROR WriteSpatialExtensionFrame( |
715 | 0 | HANDLE_FDK_BITSTREAM bitstream, HANDLE_BSF_INSTANCE self) { |
716 | 0 | FDK_SACENC_ERROR error = SACENC_OK; |
717 | |
|
718 | 0 | if ((bitstream == NULL) || (self == NULL)) { |
719 | 0 | error = SACENC_INVALID_HANDLE; |
720 | 0 | } else { |
721 | 0 | FDKbyteAlign(bitstream, 0); |
722 | 0 | } /* valid handle */ |
723 | |
|
724 | 0 | return error; |
725 | 0 | } |
726 | | |
727 | | /* write frame data to stream */ |
728 | | FDK_SACENC_ERROR fdk_sacenc_writeSpatialFrame(UCHAR *const pOutputBuffer, |
729 | | const INT outputBufferSize, |
730 | | INT *const pnOutputBits, |
731 | 0 | HANDLE_BSF_INSTANCE selfPtr) { |
732 | 0 | FDK_SACENC_ERROR error = SACENC_OK; |
733 | |
|
734 | 0 | if ((pOutputBuffer == NULL) || (pnOutputBits == NULL) || (selfPtr == NULL)) { |
735 | 0 | error = SACENC_INVALID_HANDLE; |
736 | 0 | } else { |
737 | 0 | SPATIALFRAME *frame = NULL; |
738 | 0 | SPATIALSPECIFICCONFIG *config = NULL; |
739 | 0 | FDK_BITSTREAM bitstream; |
740 | |
|
741 | 0 | int i, j, numParamSets, numOttBoxes; |
742 | |
|
743 | 0 | if ((NULL == |
744 | 0 | (frame = fdk_sacenc_getSpatialFrame(selfPtr, READ_SPATIALFRAME))) || |
745 | 0 | (NULL == (config = &(selfPtr->spatialSpecificConfig)))) { |
746 | 0 | error = SACENC_INVALID_HANDLE; |
747 | 0 | goto bail; |
748 | 0 | } |
749 | | |
750 | 0 | numOttBoxes = selfPtr->spatialSpecificConfig.treeDescription.numOttBoxes; |
751 | |
|
752 | 0 | numParamSets = frame->framingInfo.numParamSets; |
753 | |
|
754 | 0 | if (frame->bUseBBCues) { |
755 | 0 | for (i = 0; i < SACENC_MAX_NUM_BOXES; i++) { |
756 | | /* If a transient was detected, force only the second ps broad band */ |
757 | 0 | if (numParamSets == 1) { |
758 | 0 | frame->CLDLosslessData.bsFreqResStrideXXX[i][0] = 3; |
759 | 0 | frame->ICCLosslessData.bsFreqResStrideXXX[i][0] = 3; |
760 | 0 | } else { |
761 | 0 | for (j = 1; j < MAX_NUM_PARAMS; j++) { |
762 | 0 | frame->CLDLosslessData.bsFreqResStrideXXX[i][j] = 3; |
763 | 0 | frame->ICCLosslessData.bsFreqResStrideXXX[i][j] = 3; |
764 | 0 | } |
765 | 0 | } |
766 | 0 | } |
767 | 0 | } /* frame->bUseBBCues */ |
768 | | |
769 | | /* bind extern buffer to bitstream handle */ |
770 | 0 | FDKinitBitStream(&bitstream, pOutputBuffer, outputBufferSize, 0, BS_WRITER); |
771 | |
|
772 | 0 | if (SACENC_OK != (error = writeFramingInfo( |
773 | 0 | &bitstream, &(frame->framingInfo), |
774 | 0 | selfPtr->spatialSpecificConfig.bsFrameLength))) { |
775 | 0 | goto bail; |
776 | 0 | } |
777 | | |
778 | | /* write bsIndependencyFlag */ |
779 | 0 | FDKwriteBits(&bitstream, frame->bsIndependencyFlag, 1); |
780 | | |
781 | | /* write spatial data to bitstream */ |
782 | 0 | if (SACENC_OK != |
783 | 0 | (error = writeOttData(&bitstream, &selfPtr->prevFrameData.prevOttData, |
784 | 0 | &frame->ottData, config->ottConfig, |
785 | 0 | &frame->CLDLosslessData, &frame->ICCLosslessData, |
786 | 0 | numOttBoxes, config->numBands, numParamSets, |
787 | 0 | frame->bsIndependencyFlag))) { |
788 | 0 | goto bail; |
789 | 0 | } |
790 | 0 | if (SACENC_OK != (error = writeSmgData(&bitstream, &frame->smgData, |
791 | 0 | numParamSets, config->numBands))) { |
792 | 0 | goto bail; |
793 | 0 | } |
794 | | |
795 | | /* byte alignment */ |
796 | 0 | FDKbyteAlign(&bitstream, 0); |
797 | | |
798 | | /* Write SpatialExtensionFrame */ |
799 | 0 | if (SACENC_OK != |
800 | 0 | (error = WriteSpatialExtensionFrame(&bitstream, selfPtr))) { |
801 | 0 | goto bail; |
802 | 0 | } |
803 | | |
804 | 0 | if (NULL == |
805 | 0 | (frame = fdk_sacenc_getSpatialFrame(selfPtr, WRITE_SPATIALFRAME))) { |
806 | 0 | error = SACENC_INVALID_HANDLE; |
807 | 0 | goto bail; |
808 | 0 | } |
809 | | |
810 | 0 | clearFrame(frame); |
811 | | |
812 | | /* return number of valid bits in bitstream */ |
813 | 0 | if ((*pnOutputBits = FDKgetValidBits(&bitstream)) > |
814 | 0 | (outputBufferSize * 8)) { |
815 | 0 | error = SACENC_INVALID_CONFIG; |
816 | 0 | goto bail; |
817 | 0 | } |
818 | | |
819 | | /* terminate buffer with alignment */ |
820 | 0 | FDKbyteAlign(&bitstream, 0); |
821 | |
|
822 | 0 | } /* valid handle */ |
823 | | |
824 | 0 | bail: |
825 | 0 | return error; |
826 | 0 | } |