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