Home | History | Annotate | Download | only in src
      1 /* -----------------------------------------------------------------------------
      2 Software License for The Fraunhofer FDK AAC Codec Library for Android
      3 
      4  Copyright  1995 - 2018 Fraunhofer-Gesellschaft zur Frderung 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 (at) 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 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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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