/src/aac/libAACenc/src/mps_main.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 | | /**************************** AAC encoder library ****************************** |
96 | | |
97 | | Author(s): Markus Lohwasser |
98 | | |
99 | | Description: Mpeg Surround library interface functions |
100 | | |
101 | | *******************************************************************************/ |
102 | | |
103 | | /* Includes ******************************************************************/ |
104 | | #include "mps_main.h" |
105 | | #include "sacenc_lib.h" |
106 | | |
107 | | /* Data Types ****************************************************************/ |
108 | | struct MPS_ENCODER { |
109 | | HANDLE_MP4SPACE_ENCODER hSacEncoder; |
110 | | |
111 | | AUDIO_OBJECT_TYPE audioObjectType; |
112 | | |
113 | | FDK_bufDescr inBufDesc; |
114 | | FDK_bufDescr outBufDesc; |
115 | | SACENC_InArgs inargs; |
116 | | SACENC_OutArgs outargs; |
117 | | |
118 | | void *pInBuffer[1]; |
119 | | UINT pInBufferSize[1]; |
120 | | UINT pInBufferElSize[1]; |
121 | | UINT pInBufferType[1]; |
122 | | |
123 | | void *pOutBuffer[2]; |
124 | | UINT pOutBufferSize[2]; |
125 | | UINT pOutBufferElSize[2]; |
126 | | UINT pOutBufferType[2]; |
127 | | |
128 | | UCHAR sacOutBuffer[1024]; /* Worst case memory consumption for ELDv2: 768 |
129 | | bytes => 6144 bits (Core + SBR + MPS) */ |
130 | | }; |
131 | | |
132 | | struct MPS_CONFIG_TAB { |
133 | | AUDIO_OBJECT_TYPE audio_object_type; |
134 | | CHANNEL_MODE channel_mode; |
135 | | ULONG sbr_ratio; |
136 | | ULONG sampling_rate; |
137 | | ULONG bitrate_min; |
138 | | ULONG bitrate_max; |
139 | | }; |
140 | | |
141 | | /* Constants *****************************************************************/ |
142 | | static const MPS_CONFIG_TAB mpsConfigTab[] = { |
143 | | {AOT_ER_AAC_ELD, MODE_212, 0, 16000, 16000, 39999}, |
144 | | {AOT_ER_AAC_ELD, MODE_212, 0, 22050, 16000, 49999}, |
145 | | {AOT_ER_AAC_ELD, MODE_212, 0, 24000, 16000, 61999}, |
146 | | {AOT_ER_AAC_ELD, MODE_212, 0, 32000, 20000, 84999}, |
147 | | {AOT_ER_AAC_ELD, MODE_212, 0, 44100, 50000, 192000}, |
148 | | {AOT_ER_AAC_ELD, MODE_212, 0, 48000, 62000, 192000}, |
149 | | |
150 | | {AOT_ER_AAC_ELD, MODE_212, 1, 16000, 18000, 31999}, |
151 | | {AOT_ER_AAC_ELD, MODE_212, 1, 22050, 18000, 31999}, |
152 | | {AOT_ER_AAC_ELD, MODE_212, 1, 24000, 20000, 64000}, |
153 | | |
154 | | {AOT_ER_AAC_ELD, MODE_212, 2, 32000, 18000, 64000}, |
155 | | {AOT_ER_AAC_ELD, MODE_212, 2, 44100, 21000, 64000}, |
156 | | {AOT_ER_AAC_ELD, MODE_212, 2, 48000, 26000, 64000} |
157 | | |
158 | | }; |
159 | | |
160 | | /* Function / Class Declarations *********************************************/ |
161 | | |
162 | | /* Function / Class Definition ***********************************************/ |
163 | | static INT FDK_MpegsEnc_WriteFrameHeader(HANDLE_MPS_ENCODER hMpsEnc, |
164 | | UCHAR *const pOutputBuffer, |
165 | | const int outputBufferSize); |
166 | | |
167 | 0 | MPS_ENCODER_ERROR FDK_MpegsEnc_Open(HANDLE_MPS_ENCODER *phMpsEnc) { |
168 | 0 | MPS_ENCODER_ERROR error = MPS_ENCODER_OK; |
169 | 0 | HANDLE_MPS_ENCODER hMpsEnc = NULL; |
170 | |
|
171 | 0 | if (phMpsEnc == NULL) { |
172 | 0 | error = MPS_ENCODER_INVALID_HANDLE; |
173 | 0 | goto bail; |
174 | 0 | } |
175 | | |
176 | 0 | if (NULL == |
177 | 0 | (hMpsEnc = (HANDLE_MPS_ENCODER)FDKcalloc(1, sizeof(MPS_ENCODER)))) { |
178 | 0 | error = MPS_ENCODER_MEMORY_ERROR; |
179 | 0 | goto bail; |
180 | 0 | } |
181 | 0 | FDKmemclear(hMpsEnc, sizeof(MPS_ENCODER)); |
182 | |
|
183 | 0 | if (SACENC_OK != FDK_sacenc_open(&hMpsEnc->hSacEncoder)) { |
184 | 0 | error = MPS_ENCODER_MEMORY_ERROR; |
185 | 0 | goto bail; |
186 | 0 | } |
187 | | |
188 | | /* Return mps encoder instance */ |
189 | 0 | *phMpsEnc = hMpsEnc; |
190 | |
|
191 | 0 | bail: |
192 | 0 | if (error != MPS_ENCODER_OK) { |
193 | 0 | FDK_MpegsEnc_Close(&hMpsEnc); |
194 | 0 | } |
195 | 0 | return error; |
196 | 0 | } |
197 | | |
198 | 0 | MPS_ENCODER_ERROR FDK_MpegsEnc_Close(HANDLE_MPS_ENCODER *phMpsEnc) { |
199 | 0 | MPS_ENCODER_ERROR error = MPS_ENCODER_OK; |
200 | |
|
201 | 0 | if (phMpsEnc == NULL) { |
202 | 0 | error = MPS_ENCODER_INVALID_HANDLE; |
203 | 0 | goto bail; |
204 | 0 | } |
205 | | |
206 | 0 | if (*phMpsEnc != NULL) { |
207 | 0 | FDK_sacenc_close(&(*phMpsEnc)->hSacEncoder); |
208 | 0 | FDKfree(*phMpsEnc); |
209 | 0 | *phMpsEnc = NULL; |
210 | 0 | } |
211 | 0 | bail: |
212 | 0 | return error; |
213 | 0 | } |
214 | | |
215 | | MPS_ENCODER_ERROR FDK_MpegsEnc_Init(HANDLE_MPS_ENCODER hMpsEnc, |
216 | | const AUDIO_OBJECT_TYPE audioObjectType, |
217 | | const UINT samplingrate, const UINT bitrate, |
218 | | const UINT sbrRatio, const UINT framelength, |
219 | | const UINT inputBufferSizePerChannel, |
220 | 0 | const UINT coreCoderDelay) { |
221 | 0 | MPS_ENCODER_ERROR error = MPS_ENCODER_OK; |
222 | 0 | const UINT fs_low = 27713; /* low MPS sampling frequencies */ |
223 | 0 | const UINT fs_high = 55426; /* high MPS sampling frequencies */ |
224 | 0 | UINT nTimeSlots = 0, nQmfBandsLd = 0; |
225 | |
|
226 | 0 | if (hMpsEnc == NULL) { |
227 | 0 | error = MPS_ENCODER_INVALID_HANDLE; |
228 | 0 | goto bail; |
229 | 0 | } |
230 | | |
231 | | /* Combine MPS with SBR only if the number of QMF band fits together.*/ |
232 | 0 | switch (sbrRatio) { |
233 | 0 | case 1: /* downsampled sbr - 32 QMF bands required */ |
234 | 0 | if (!(samplingrate < fs_low)) { |
235 | 0 | error = MPS_ENCODER_INIT_ERROR; |
236 | 0 | goto bail; |
237 | 0 | } |
238 | 0 | break; |
239 | 0 | case 2: /* dualrate - 64 QMF bands required */ |
240 | 0 | if (!((samplingrate >= fs_low) && (samplingrate < fs_high))) { |
241 | 0 | error = MPS_ENCODER_INIT_ERROR; |
242 | 0 | goto bail; |
243 | 0 | } |
244 | 0 | break; |
245 | 0 | case 0: |
246 | 0 | default:; /* time interface - no samplingrate restriction */ |
247 | 0 | } |
248 | | |
249 | | /* 32 QMF-Bands ( fs < 27713 ) |
250 | | * 64 QMF-Bands ( 27713 >= fs <= 55426 ) |
251 | | * 128 QMF-Bands ( fs > 55426 ) |
252 | | */ |
253 | 0 | nQmfBandsLd = |
254 | 0 | (samplingrate < fs_low) ? 5 : ((samplingrate > fs_high) ? 7 : 6); |
255 | 0 | nTimeSlots = framelength >> nQmfBandsLd; |
256 | | |
257 | | /* check if number of qmf bands is usable for given framelength */ |
258 | 0 | if (framelength != (nTimeSlots << nQmfBandsLd)) { |
259 | 0 | error = MPS_ENCODER_INIT_ERROR; |
260 | 0 | goto bail; |
261 | 0 | } |
262 | | |
263 | | /* is given bitrate intended to be supported */ |
264 | 0 | if ((INT)bitrate != FDK_MpegsEnc_GetClosestBitRate(audioObjectType, MODE_212, |
265 | 0 | samplingrate, sbrRatio, |
266 | 0 | bitrate)) { |
267 | 0 | error = MPS_ENCODER_INIT_ERROR; |
268 | 0 | goto bail; |
269 | 0 | } |
270 | | |
271 | | /* init SAC library */ |
272 | 0 | switch (audioObjectType) { |
273 | 0 | case AOT_ER_AAC_ELD: { |
274 | 0 | const UINT noInterFrameCoding = 0; |
275 | |
|
276 | 0 | if ((SACENC_OK != |
277 | 0 | FDK_sacenc_setParam(hMpsEnc->hSacEncoder, SACENC_LOWDELAY, |
278 | 0 | (noInterFrameCoding == 1) ? 1 : 2)) || |
279 | 0 | (SACENC_OK != FDK_sacenc_setParam(hMpsEnc->hSacEncoder, |
280 | 0 | SACENC_ENC_MODE, SACENC_212)) || |
281 | 0 | (SACENC_OK != FDK_sacenc_setParam(hMpsEnc->hSacEncoder, |
282 | 0 | SACENC_SAMPLERATE, samplingrate)) || |
283 | 0 | (SACENC_OK != FDK_sacenc_setParam(hMpsEnc->hSacEncoder, |
284 | 0 | SACENC_FRAME_TIME_SLOTS, |
285 | 0 | nTimeSlots)) || |
286 | 0 | (SACENC_OK != FDK_sacenc_setParam(hMpsEnc->hSacEncoder, |
287 | 0 | SACENC_PARAM_BANDS, |
288 | 0 | SACENC_BANDS_15)) || |
289 | 0 | (SACENC_OK != |
290 | 0 | FDK_sacenc_setParam(hMpsEnc->hSacEncoder, SACENC_TIME_DOM_DMX, 2)) || |
291 | 0 | (SACENC_OK != |
292 | 0 | FDK_sacenc_setParam(hMpsEnc->hSacEncoder, SACENC_COARSE_QUANT, 0)) || |
293 | 0 | (SACENC_OK != FDK_sacenc_setParam(hMpsEnc->hSacEncoder, |
294 | 0 | SACENC_QUANT_MODE, |
295 | 0 | SACENC_QUANTMODE_FINE)) || |
296 | 0 | (SACENC_OK != FDK_sacenc_setParam(hMpsEnc->hSacEncoder, |
297 | 0 | SACENC_TIME_ALIGNMENT, 0)) || |
298 | 0 | (SACENC_OK != FDK_sacenc_setParam(hMpsEnc->hSacEncoder, |
299 | 0 | SACENC_INDEPENDENCY_FACTOR, 20))) { |
300 | 0 | error = MPS_ENCODER_INIT_ERROR; |
301 | 0 | goto bail; |
302 | 0 | } |
303 | 0 | break; |
304 | 0 | } |
305 | 0 | default: |
306 | 0 | error = MPS_ENCODER_INIT_ERROR; |
307 | 0 | goto bail; |
308 | 0 | } |
309 | | |
310 | 0 | if (SACENC_OK != FDK_sacenc_init(hMpsEnc->hSacEncoder, coreCoderDelay)) { |
311 | 0 | error = MPS_ENCODER_INIT_ERROR; |
312 | 0 | } |
313 | |
|
314 | 0 | hMpsEnc->audioObjectType = audioObjectType; |
315 | |
|
316 | 0 | hMpsEnc->inBufDesc.ppBase = (void **)&hMpsEnc->pInBuffer; |
317 | 0 | hMpsEnc->inBufDesc.pBufSize = hMpsEnc->pInBufferSize; |
318 | 0 | hMpsEnc->inBufDesc.pEleSize = hMpsEnc->pInBufferElSize; |
319 | 0 | hMpsEnc->inBufDesc.pBufType = hMpsEnc->pInBufferType; |
320 | 0 | hMpsEnc->inBufDesc.numBufs = 1; |
321 | |
|
322 | 0 | hMpsEnc->outBufDesc.ppBase = (void **)&hMpsEnc->pOutBuffer; |
323 | 0 | hMpsEnc->outBufDesc.pBufSize = hMpsEnc->pOutBufferSize; |
324 | 0 | hMpsEnc->outBufDesc.pEleSize = hMpsEnc->pOutBufferElSize; |
325 | 0 | hMpsEnc->outBufDesc.pBufType = hMpsEnc->pOutBufferType; |
326 | 0 | hMpsEnc->outBufDesc.numBufs = 2; |
327 | |
|
328 | 0 | hMpsEnc->pInBuffer[0] = NULL; |
329 | 0 | hMpsEnc->pInBufferSize[0] = 0; |
330 | 0 | hMpsEnc->pInBufferElSize[0] = sizeof(INT_PCM); |
331 | 0 | hMpsEnc->pInBufferType[0] = (FDK_BUF_TYPE_INPUT | FDK_BUF_TYPE_PCM_DATA); |
332 | |
|
333 | 0 | hMpsEnc->pOutBuffer[0] = NULL; |
334 | 0 | hMpsEnc->pOutBufferSize[0] = 0; |
335 | 0 | hMpsEnc->pOutBufferElSize[0] = sizeof(INT_PCM); |
336 | 0 | hMpsEnc->pOutBufferType[0] = (FDK_BUF_TYPE_OUTPUT | FDK_BUF_TYPE_PCM_DATA); |
337 | |
|
338 | 0 | hMpsEnc->pOutBuffer[1] = NULL; |
339 | 0 | hMpsEnc->pOutBufferSize[1] = 0; |
340 | 0 | hMpsEnc->pOutBufferElSize[1] = sizeof(UCHAR); |
341 | 0 | hMpsEnc->pOutBufferType[1] = (FDK_BUF_TYPE_OUTPUT | FDK_BUF_TYPE_BS_DATA); |
342 | |
|
343 | 0 | hMpsEnc->inargs.isInputInterleaved = 0; |
344 | 0 | hMpsEnc->inargs.inputBufferSizePerChannel = inputBufferSizePerChannel; |
345 | |
|
346 | 0 | bail: |
347 | 0 | return error; |
348 | 0 | } |
349 | | |
350 | | MPS_ENCODER_ERROR FDK_MpegsEnc_Process(HANDLE_MPS_ENCODER hMpsEnc, |
351 | | INT_PCM *const pAudioSamples, |
352 | | const INT nAudioSamples, |
353 | 0 | AACENC_EXT_PAYLOAD *pMpsExtPayload) { |
354 | 0 | MPS_ENCODER_ERROR error = MPS_ENCODER_OK; |
355 | |
|
356 | 0 | if (hMpsEnc == NULL) { |
357 | 0 | error = MPS_ENCODER_INVALID_HANDLE; |
358 | 0 | } else { |
359 | 0 | int sacHeaderFlag = 1; |
360 | 0 | int sacOutBufferOffset = 0; |
361 | | |
362 | | /* In case of eld the ssc is explicit and doesn't need to be inband */ |
363 | 0 | if (hMpsEnc->audioObjectType == AOT_ER_AAC_ELD) { |
364 | 0 | sacHeaderFlag = 0; |
365 | 0 | } |
366 | | |
367 | | /* 4 bits nibble after extension type */ |
368 | 0 | hMpsEnc->sacOutBuffer[0] = (sacHeaderFlag == 0) ? 0x3 : 0x7; |
369 | 0 | sacOutBufferOffset += 1; |
370 | |
|
371 | 0 | if (sacHeaderFlag) { |
372 | 0 | sacOutBufferOffset += FDK_MpegsEnc_WriteFrameHeader( |
373 | 0 | hMpsEnc, &hMpsEnc->sacOutBuffer[sacOutBufferOffset], |
374 | 0 | sizeof(hMpsEnc->sacOutBuffer) - sacOutBufferOffset); |
375 | 0 | } |
376 | | |
377 | | /* Register input and output buffer. */ |
378 | 0 | hMpsEnc->pInBuffer[0] = (void *)pAudioSamples; |
379 | 0 | hMpsEnc->inargs.nInputSamples = nAudioSamples; |
380 | |
|
381 | 0 | hMpsEnc->pOutBuffer[0] = (void *)pAudioSamples; |
382 | 0 | hMpsEnc->pOutBufferSize[0] = sizeof(INT_PCM) * nAudioSamples / 2; |
383 | |
|
384 | 0 | hMpsEnc->pOutBuffer[1] = (void *)&hMpsEnc->sacOutBuffer[sacOutBufferOffset]; |
385 | 0 | hMpsEnc->pOutBufferSize[1] = |
386 | 0 | sizeof(hMpsEnc->sacOutBuffer) - sacOutBufferOffset; |
387 | | |
388 | | /* encode SAC frame */ |
389 | 0 | if (SACENC_OK != FDK_sacenc_encode(hMpsEnc->hSacEncoder, |
390 | 0 | &hMpsEnc->inBufDesc, |
391 | 0 | &hMpsEnc->outBufDesc, &hMpsEnc->inargs, |
392 | 0 | &hMpsEnc->outargs)) { |
393 | 0 | error = MPS_ENCODER_ENCODE_ERROR; |
394 | 0 | goto bail; |
395 | 0 | } |
396 | | |
397 | | /* export MPS payload */ |
398 | 0 | pMpsExtPayload->pData = (UCHAR *)hMpsEnc->sacOutBuffer; |
399 | 0 | pMpsExtPayload->dataSize = |
400 | 0 | hMpsEnc->outargs.nOutputBits + 8 * (sacOutBufferOffset - 1); |
401 | 0 | pMpsExtPayload->dataType = EXT_LDSAC_DATA; |
402 | 0 | pMpsExtPayload->associatedChElement = -1; |
403 | 0 | } |
404 | | |
405 | 0 | bail: |
406 | 0 | return error; |
407 | 0 | } |
408 | | |
409 | | INT FDK_MpegsEnc_WriteSpatialSpecificConfig(HANDLE_MPS_ENCODER hMpsEnc, |
410 | 0 | HANDLE_FDK_BITSTREAM hBs) { |
411 | 0 | INT sscBits = 0; |
412 | |
|
413 | 0 | if (NULL != hMpsEnc) { |
414 | 0 | MP4SPACEENC_INFO mp4SpaceEncoderInfo; |
415 | 0 | FDK_sacenc_getInfo(hMpsEnc->hSacEncoder, &mp4SpaceEncoderInfo); |
416 | |
|
417 | 0 | if (hBs != NULL) { |
418 | 0 | int i; |
419 | 0 | int writtenBits = 0; |
420 | 0 | for (i = 0; i<mp4SpaceEncoderInfo.pSscBuf->nSscSizeBits>> 3; i++) { |
421 | 0 | FDKwriteBits(hBs, mp4SpaceEncoderInfo.pSscBuf->pSsc[i], 8); |
422 | 0 | writtenBits += 8; |
423 | 0 | } |
424 | 0 | FDKwriteBits(hBs, mp4SpaceEncoderInfo.pSscBuf->pSsc[i], |
425 | 0 | mp4SpaceEncoderInfo.pSscBuf->nSscSizeBits - writtenBits); |
426 | 0 | } /* hBS */ |
427 | |
|
428 | 0 | sscBits = mp4SpaceEncoderInfo.pSscBuf->nSscSizeBits; |
429 | |
|
430 | 0 | } /* valid hMpsEnc */ |
431 | |
|
432 | 0 | return sscBits; |
433 | 0 | } |
434 | | |
435 | | static INT FDK_MpegsEnc_WriteFrameHeader(HANDLE_MPS_ENCODER hMpsEnc, |
436 | | UCHAR *const pOutputBuffer, |
437 | 0 | const int outputBufferSize) { |
438 | 0 | const int sacTimeAlignFlag = 0; |
439 | | |
440 | | /* Initialize variables */ |
441 | 0 | int numBits = 0; |
442 | |
|
443 | 0 | if ((NULL != hMpsEnc) && (NULL != pOutputBuffer)) { |
444 | 0 | UINT alignAnchor, cnt; |
445 | 0 | FDK_BITSTREAM Bs; |
446 | 0 | FDKinitBitStream(&Bs, pOutputBuffer, outputBufferSize, 0, BS_WRITER); |
447 | | |
448 | | /* Calculate SSC length information */ |
449 | 0 | cnt = (FDK_MpegsEnc_WriteSpatialSpecificConfig(hMpsEnc, NULL) + 7) >> 3; |
450 | | |
451 | | /* Write SSC */ |
452 | 0 | FDKwriteBits(&Bs, sacTimeAlignFlag, 1); |
453 | |
|
454 | 0 | if (cnt < 127) { |
455 | 0 | FDKwriteBits(&Bs, cnt, 7); |
456 | 0 | } else { |
457 | 0 | FDKwriteBits(&Bs, 127, 7); |
458 | 0 | FDKwriteBits(&Bs, cnt - 127, 16); |
459 | 0 | } |
460 | |
|
461 | 0 | alignAnchor = FDKgetValidBits(&Bs); |
462 | 0 | FDK_MpegsEnc_WriteSpatialSpecificConfig(hMpsEnc, &Bs); |
463 | 0 | FDKbyteAlign(&Bs, alignAnchor); /* bsFillBits */ |
464 | |
|
465 | 0 | if (sacTimeAlignFlag) { |
466 | 0 | FDK_ASSERT(1); /* time alignment not supported */ |
467 | 0 | } |
468 | | |
469 | 0 | numBits = FDKgetValidBits(&Bs); |
470 | 0 | } /* valid handle */ |
471 | | |
472 | 0 | return ((numBits + 7) >> 3); |
473 | 0 | } |
474 | | |
475 | | INT FDK_MpegsEnc_GetClosestBitRate(const AUDIO_OBJECT_TYPE audioObjectType, |
476 | | const CHANNEL_MODE channelMode, |
477 | | const UINT samplingrate, const UINT sbrRatio, |
478 | 0 | const UINT bitrate) { |
479 | 0 | unsigned int i; |
480 | 0 | int targetBitrate = -1; |
481 | |
|
482 | 0 | for (i = 0; i < sizeof(mpsConfigTab) / sizeof(MPS_CONFIG_TAB); i++) { |
483 | 0 | if ((mpsConfigTab[i].audio_object_type == audioObjectType) && |
484 | 0 | (mpsConfigTab[i].channel_mode == channelMode) && |
485 | 0 | (mpsConfigTab[i].sbr_ratio == sbrRatio) && |
486 | 0 | (mpsConfigTab[i].sampling_rate == samplingrate)) { |
487 | 0 | targetBitrate = fMin(fMax(bitrate, mpsConfigTab[i].bitrate_min), |
488 | 0 | mpsConfigTab[i].bitrate_max); |
489 | 0 | } |
490 | 0 | } |
491 | |
|
492 | 0 | return targetBitrate; |
493 | 0 | } |
494 | | |
495 | 0 | INT FDK_MpegsEnc_GetDelay(HANDLE_MPS_ENCODER hMpsEnc) { |
496 | 0 | INT delay = 0; |
497 | |
|
498 | 0 | if (NULL != hMpsEnc) { |
499 | 0 | MP4SPACEENC_INFO mp4SpaceEncoderInfo; |
500 | 0 | FDK_sacenc_getInfo(hMpsEnc->hSacEncoder, &mp4SpaceEncoderInfo); |
501 | 0 | delay = mp4SpaceEncoderInfo.nCodecDelay; |
502 | 0 | } |
503 | |
|
504 | 0 | return delay; |
505 | 0 | } |
506 | | |
507 | 0 | INT FDK_MpegsEnc_GetDecDelay(HANDLE_MPS_ENCODER hMpsEnc) { |
508 | 0 | INT delay = 0; |
509 | |
|
510 | 0 | if (NULL != hMpsEnc) { |
511 | 0 | MP4SPACEENC_INFO mp4SpaceEncoderInfo; |
512 | 0 | FDK_sacenc_getInfo(hMpsEnc->hSacEncoder, &mp4SpaceEncoderInfo); |
513 | 0 | delay = mp4SpaceEncoderInfo.nDecoderDelay; |
514 | 0 | } |
515 | |
|
516 | 0 | return delay; |
517 | 0 | } |
518 | | |
519 | 0 | MPS_ENCODER_ERROR FDK_MpegsEnc_GetLibInfo(LIB_INFO *info) { |
520 | 0 | MPS_ENCODER_ERROR error = MPS_ENCODER_OK; |
521 | |
|
522 | 0 | if (NULL == info) { |
523 | 0 | error = MPS_ENCODER_INVALID_HANDLE; |
524 | 0 | } else if (SACENC_OK != FDK_sacenc_getLibInfo(info)) { |
525 | 0 | error = MPS_ENCODER_INIT_ERROR; |
526 | 0 | } |
527 | |
|
528 | 0 | return error; |
529 | 0 | } |