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 /******************* MPEG transport format encoder library *********************
     96 
     97    Author(s):   Manuel Jander
     98 
     99    Description: MPEG Transport encode
    100 
    101 *******************************************************************************/
    102 
    103 #include "tpenc_lib.h"
    104 
    105 /* library info */
    106 #include "tp_version.h"
    107 
    108 #define MODULE_NAME "transportEnc"
    109 
    110 #include "tpenc_asc.h"
    111 
    112 #include "tpenc_adts.h"
    113 
    114 #include "tpenc_adif.h"
    115 
    116 #include "tpenc_latm.h"
    117 
    118 typedef struct {
    119   int curSubFrame;
    120   int nSubFrames;
    121   int prevBits;
    122 } RAWPACKETS_INFO;
    123 
    124 struct TRANSPORTENC {
    125   CODER_CONFIG config;
    126   TRANSPORT_TYPE transportFmt; /*!< MPEG4 transport type. */
    127 
    128   FDK_BITSTREAM bitStream;
    129   UCHAR *bsBuffer;
    130   INT bsBufferSize;
    131 
    132   INT pceFrameCounter; /*!< Indicates frame period when PCE must be written in
    133                           raw_data_block. -1 means not to write a PCE in
    134                           raw_dat_block. */
    135   union {
    136     STRUCT_ADTS adts;
    137 
    138     ADIF_INFO adif;
    139 
    140     LATM_STREAM latm;
    141 
    142     RAWPACKETS_INFO raw;
    143 
    144   } writer;
    145 
    146   CSTpCallBacks callbacks;
    147 };
    148 
    149 typedef struct _TRANSPORTENC_STRUCT TRANSPORTENC_STRUCT;
    150 
    151 /*
    152  * MEMORY Declaration
    153  */
    154 
    155 C_ALLOC_MEM(Ram_TransportEncoder, struct TRANSPORTENC, 1)
    156 
    157 TRANSPORTENC_ERROR transportEnc_Open(HANDLE_TRANSPORTENC *phTpEnc) {
    158   HANDLE_TRANSPORTENC hTpEnc;
    159 
    160   if (phTpEnc == NULL) {
    161     return TRANSPORTENC_INVALID_PARAMETER;
    162   }
    163 
    164   hTpEnc = GetRam_TransportEncoder(0);
    165 
    166   if (hTpEnc == NULL) {
    167     return TRANSPORTENC_NO_MEM;
    168   }
    169 
    170   *phTpEnc = hTpEnc;
    171   return TRANSPORTENC_OK;
    172 }
    173 
    174 /**
    175  * \brief  Get frame period of PCE in raw_data_block.
    176  *
    177  * - Write PCE only if necessary. PCE can be part of the ASC if chConfig==0
    178  * whererfore no additonal PCE will be written in raw_data_block.
    179  * - A matrixMixdown coefficient can only be written if chConfig is 5.0 or 5.1.
    180  * - The PCE repetition rate in raw_data_block can be controlled via
    181  * headerPeriod parameter.
    182  *
    183  * \param channelMode           Encoder Channel Mode.
    184  * \param channelConfigZero     No standard channel configuration.
    185  * \param transportFmt          Format of the transport to be written.
    186  * \param headerPeriod          Chosen PCE frame repetition rate.
    187  * \param matrixMixdownA        Indicates if a valid Matrix Mixdown coefficient
    188  * is available.
    189  *
    190  * \return  PCE frame repetition rate. -1 means no PCE present in
    191  * raw_data_block.
    192  */
    193 static INT getPceRepetitionRate(const CHANNEL_MODE channelMode,
    194                                 const int channelConfigZero,
    195                                 const TRANSPORT_TYPE transportFmt,
    196                                 const int headerPeriod,
    197                                 const int matrixMixdownA) {
    198   INT pceFrameCounter = -1; /* variable to be returned */
    199 
    200   if (headerPeriod > 0) {
    201     switch (getChannelConfig(channelMode, channelConfigZero)) {
    202       case 0:
    203         switch (transportFmt) {
    204           case TT_MP4_ADTS:
    205           case TT_MP4_LATM_MCP0:
    206           case TT_MP4_RAW:
    207             pceFrameCounter = headerPeriod;
    208             break;
    209           case TT_MP4_ADIF: /* ADIF header comprises PCE */
    210             if ((channelMode == MODE_1_2_2) || (channelMode == MODE_1_2_2_1)) {
    211               pceFrameCounter = headerPeriod; /* repeating pce only meaningful
    212                                                  for potential matrix mixdown */
    213               break;
    214             }
    215           case TT_MP4_LOAS:      /* PCE in ASC if chChonfig==0 */
    216           case TT_MP4_LATM_MCP1: /* PCE in ASC if chChonfig==0 */
    217           default:
    218             pceFrameCounter = -1; /* no PCE in raw_data_block */
    219         }
    220         break;
    221       case 5: /* MODE_1_2_2 */
    222       case 6: /* MODE_1_2_2_1 */
    223         /* matrixMixdownCoefficient can only be written if 5.0 and 5.1 config
    224          * present. */
    225         if (matrixMixdownA != 0) {
    226           switch (transportFmt) {
    227             case TT_MP4_ADIF: /* ADIF header comprises PCE */
    228             case TT_MP4_ADTS:
    229             case TT_MP4_LOAS:      /* no PCE in ASC because chConfig!=0 */
    230             case TT_MP4_LATM_MCP1: /* no PCE in ASC because chConfig!=0 */
    231             case TT_MP4_LATM_MCP0:
    232             case TT_MP4_RAW:
    233               pceFrameCounter = headerPeriod;
    234               break;
    235             default:
    236               pceFrameCounter = -1; /* no PCE in raw_data_block */
    237           }                         /* switch transportFmt */
    238         }                           /* if matrixMixdownA!=0 */
    239         break;
    240       default:
    241         pceFrameCounter = -1; /* no PCE in raw_data_block */
    242     }                         /* switch getChannelConfig() */
    243   }                           /* if headerPeriod>0  */
    244   else {
    245     pceFrameCounter = -1; /* no PCE in raw_data_block */
    246   }
    247 
    248   return pceFrameCounter;
    249 }
    250 
    251 TRANSPORTENC_ERROR transportEnc_Init(HANDLE_TRANSPORTENC hTpEnc,
    252                                      UCHAR *bsBuffer, INT bsBufferSize,
    253                                      TRANSPORT_TYPE transportFmt,
    254                                      CODER_CONFIG *cconfig, UINT flags) {
    255   /* Copy configuration structure */
    256   FDKmemcpy(&hTpEnc->config, cconfig, sizeof(CODER_CONFIG));
    257 
    258   /* Init transportEnc struct. */
    259   hTpEnc->transportFmt = transportFmt;
    260 
    261   hTpEnc->bsBuffer = bsBuffer;
    262   hTpEnc->bsBufferSize = bsBufferSize;
    263 
    264   FDKinitBitStream(&hTpEnc->bitStream, hTpEnc->bsBuffer, hTpEnc->bsBufferSize,
    265                    0, BS_WRITER);
    266 
    267   switch (transportFmt) {
    268     case TT_MP4_ADIF:
    269       /* Sanity checks */
    270       if ((hTpEnc->config.aot != AOT_AAC_LC) ||
    271           (hTpEnc->config.samplesPerFrame != 1024)) {
    272         return TRANSPORTENC_INVALID_PARAMETER;
    273       }
    274       hTpEnc->writer.adif.headerWritten = 0;
    275       hTpEnc->writer.adif.samplingRate = hTpEnc->config.samplingRate;
    276       hTpEnc->writer.adif.bitRate = hTpEnc->config.bitRate;
    277       hTpEnc->writer.adif.profile = ((int)hTpEnc->config.aot) - 1;
    278       hTpEnc->writer.adif.cm = hTpEnc->config.channelMode;
    279       hTpEnc->writer.adif.bVariableRate = 0;
    280       hTpEnc->writer.adif.instanceTag = 0;
    281       hTpEnc->writer.adif.matrixMixdownA = hTpEnc->config.matrixMixdownA;
    282       hTpEnc->writer.adif.pseudoSurroundEnable =
    283           (hTpEnc->config.flags & CC_PSEUDO_SURROUND) ? 1 : 0;
    284       break;
    285 
    286     case TT_MP4_ADTS:
    287       /* Sanity checks */
    288       if ((hTpEnc->config.aot != AOT_AAC_LC) ||
    289           (hTpEnc->config.samplesPerFrame != 1024)) {
    290         return TRANSPORTENC_INVALID_PARAMETER;
    291       }
    292       if (adtsWrite_Init(&hTpEnc->writer.adts, &hTpEnc->config) != 0) {
    293         return TRANSPORTENC_INVALID_PARAMETER;
    294       }
    295       break;
    296 
    297     case TT_MP4_LOAS:
    298     case TT_MP4_LATM_MCP0:
    299     case TT_MP4_LATM_MCP1: {
    300       TRANSPORTENC_ERROR error;
    301 
    302       error = transportEnc_Latm_Init(&hTpEnc->writer.latm, &hTpEnc->bitStream,
    303                                      &hTpEnc->config, flags & TP_FLAG_LATM_AMV,
    304                                      transportFmt, &hTpEnc->callbacks);
    305       if (error != TRANSPORTENC_OK) {
    306         return error;
    307       }
    308     } break;
    309 
    310     case TT_MP4_RAW:
    311       hTpEnc->writer.raw.curSubFrame = 0;
    312       hTpEnc->writer.raw.nSubFrames = hTpEnc->config.nSubFrames;
    313       break;
    314 
    315     default:
    316       return TRANSPORTENC_INVALID_PARAMETER;
    317   }
    318 
    319   /* pceFrameCounter indicates if PCE must be written in raw_data_block. */
    320   hTpEnc->pceFrameCounter = getPceRepetitionRate(
    321       hTpEnc->config.channelMode, hTpEnc->config.channelConfigZero,
    322       transportFmt, hTpEnc->config.headerPeriod, hTpEnc->config.matrixMixdownA);
    323 
    324   return TRANSPORTENC_OK;
    325 }
    326 
    327 TRANSPORTENC_ERROR transportEnc_AddOtherDataBits(HANDLE_TRANSPORTENC hTpEnc,
    328                                                  const int nBits) {
    329   TRANSPORTENC_ERROR tpErr = TRANSPORTENC_OK;
    330 
    331   switch (hTpEnc->transportFmt) {
    332     case TT_MP4_LATM_MCP0:
    333     case TT_MP4_LATM_MCP1:
    334     case TT_MP4_LOAS:
    335       tpErr = transportEnc_LatmAddOtherDataBits(&hTpEnc->writer.latm, nBits);
    336       break;
    337     case TT_MP4_ADTS:
    338     case TT_MP4_ADIF:
    339     case TT_MP4_RAW:
    340     default:
    341       tpErr = TRANSPORTENC_UNKOWN_ERROR;
    342   }
    343 
    344   return tpErr;
    345 }
    346 
    347 HANDLE_FDK_BITSTREAM transportEnc_GetBitstream(HANDLE_TRANSPORTENC hTp) {
    348   return &hTp->bitStream;
    349 }
    350 
    351 int transportEnc_RegisterSbrCallback(HANDLE_TRANSPORTENC hTpEnc,
    352                                      const cbSbr_t cbSbr, void *user_data) {
    353   if (hTpEnc == NULL) {
    354     return -1;
    355   }
    356   hTpEnc->callbacks.cbSbr = cbSbr;
    357   hTpEnc->callbacks.cbSbrData = user_data;
    358   return 0;
    359 }
    360 int transportEnc_RegisterUsacCallback(HANDLE_TRANSPORTENC hTpEnc,
    361                                       const cbUsac_t cbUsac, void *user_data) {
    362   if (hTpEnc == NULL) {
    363     return -1;
    364   }
    365   hTpEnc->callbacks.cbUsac = cbUsac;
    366   hTpEnc->callbacks.cbUsacData = user_data;
    367   return 0;
    368 }
    369 
    370 int transportEnc_RegisterSscCallback(HANDLE_TRANSPORTENC hTpEnc,
    371                                      const cbSsc_t cbSsc, void *user_data) {
    372   if (hTpEnc == NULL) {
    373     return -1;
    374   }
    375   hTpEnc->callbacks.cbSsc = cbSsc;
    376   hTpEnc->callbacks.cbSscData = user_data;
    377   return 0;
    378 }
    379 
    380 TRANSPORTENC_ERROR transportEnc_WriteAccessUnit(HANDLE_TRANSPORTENC hTp,
    381                                                 INT frameUsedBits,
    382                                                 int bufferFullness, int ncc) {
    383   TRANSPORTENC_ERROR err = TRANSPORTENC_OK;
    384 
    385   if (!hTp) {
    386     return TRANSPORTENC_INVALID_PARAMETER;
    387   }
    388   HANDLE_FDK_BITSTREAM hBs = &hTp->bitStream;
    389 
    390   /* In case of writing PCE in raw_data_block frameUsedBits must be adapted. */
    391   if (hTp->pceFrameCounter >= hTp->config.headerPeriod) {
    392     frameUsedBits += transportEnc_GetPCEBits(
    393         hTp->config.channelMode, hTp->config.matrixMixdownA,
    394         3); /* Consider 3 bits ID signalling in alignment */
    395   }
    396 
    397   switch (hTp->transportFmt) {
    398     case TT_MP4_ADIF:
    399       FDKinitBitStream(&hTp->bitStream, hTp->bsBuffer, hTp->bsBufferSize, 0,
    400                        BS_WRITER);
    401       if (0 != adifWrite_EncodeHeader(&hTp->writer.adif, hBs, bufferFullness)) {
    402         err = TRANSPORTENC_INVALID_CONFIG;
    403       }
    404       break;
    405     case TT_MP4_ADTS:
    406       bufferFullness /= ncc; /* Number of Considered Channels */
    407       bufferFullness /= 32;
    408       bufferFullness = FDKmin(0x7FF, bufferFullness); /* Signal variable rate */
    409       adtsWrite_EncodeHeader(&hTp->writer.adts, &hTp->bitStream, bufferFullness,
    410                              frameUsedBits);
    411       break;
    412     case TT_MP4_LOAS:
    413     case TT_MP4_LATM_MCP0:
    414     case TT_MP4_LATM_MCP1:
    415       bufferFullness /= ncc; /* Number of Considered Channels */
    416       bufferFullness /= 32;
    417       bufferFullness = FDKmin(0xFF, bufferFullness); /* Signal variable rate */
    418       transportEnc_LatmWrite(&hTp->writer.latm, hBs, frameUsedBits,
    419                              bufferFullness, &hTp->callbacks);
    420       break;
    421     case TT_MP4_RAW:
    422       if (hTp->writer.raw.curSubFrame >= hTp->writer.raw.nSubFrames) {
    423         hTp->writer.raw.curSubFrame = 0;
    424         FDKinitBitStream(&hTp->bitStream, hTp->bsBuffer, hTp->bsBufferSize, 0,
    425                          BS_WRITER);
    426       }
    427       hTp->writer.raw.prevBits = FDKgetValidBits(hBs);
    428       break;
    429     default:
    430       err = TRANSPORTENC_UNSUPPORTED_FORMAT;
    431       break;
    432   }
    433 
    434   /* Write PCE in raw_data_block if required */
    435   if (hTp->pceFrameCounter >= hTp->config.headerPeriod) {
    436     INT crcIndex = 0;
    437     /* Align inside PCE with repsect to the first bit of the raw_data_block() */
    438     UINT alignAnchor = FDKgetValidBits(&hTp->bitStream);
    439 
    440     /* Write PCE element ID bits */
    441     FDKwriteBits(&hTp->bitStream, ID_PCE, 3);
    442 
    443     if ((hTp->transportFmt == TT_MP4_ADTS) &&
    444         !hTp->writer.adts.protection_absent) {
    445       crcIndex = adtsWrite_CrcStartReg(&hTp->writer.adts, &hTp->bitStream, 0);
    446     }
    447 
    448     /* Write PCE as first raw_data_block element */
    449     transportEnc_writePCE(
    450         &hTp->bitStream, hTp->config.channelMode, hTp->config.samplingRate, 0,
    451         1, hTp->config.matrixMixdownA,
    452         (hTp->config.flags & CC_PSEUDO_SURROUND) ? 1 : 0, alignAnchor);
    453 
    454     if ((hTp->transportFmt == TT_MP4_ADTS) &&
    455         !hTp->writer.adts.protection_absent) {
    456       adtsWrite_CrcEndReg(&hTp->writer.adts, &hTp->bitStream, crcIndex);
    457     }
    458     hTp->pceFrameCounter = 0; /* reset pce frame counter */
    459   }
    460 
    461   if (hTp->pceFrameCounter != -1) {
    462     hTp->pceFrameCounter++; /* Update pceFrameCounter only if PCE writing is
    463                                active. */
    464   }
    465 
    466   return err;
    467 }
    468 
    469 TRANSPORTENC_ERROR transportEnc_EndAccessUnit(HANDLE_TRANSPORTENC hTp,
    470                                               int *bits) {
    471   switch (hTp->transportFmt) {
    472     case TT_MP4_LATM_MCP0:
    473     case TT_MP4_LATM_MCP1:
    474     case TT_MP4_LOAS:
    475       transportEnc_LatmAdjustSubframeBits(&hTp->writer.latm, bits);
    476       break;
    477     case TT_MP4_ADTS:
    478       adtsWrite_EndRawDataBlock(&hTp->writer.adts, &hTp->bitStream, bits);
    479       break;
    480     case TT_MP4_ADIF:
    481       /* Substract ADIF header from AU bits, not to be considered. */
    482       *bits -= adifWrite_GetHeaderBits(&hTp->writer.adif);
    483       hTp->writer.adif.headerWritten = 1;
    484       break;
    485     case TT_MP4_RAW:
    486       *bits -= hTp->writer.raw.prevBits;
    487       break;
    488     default:
    489       break;
    490   }
    491 
    492   return TRANSPORTENC_OK;
    493 }
    494 
    495 TRANSPORTENC_ERROR transportEnc_GetFrame(HANDLE_TRANSPORTENC hTpEnc,
    496                                          int *nbytes) {
    497   TRANSPORTENC_ERROR tpErr = TRANSPORTENC_OK;
    498   HANDLE_FDK_BITSTREAM hBs = &hTpEnc->bitStream;
    499 
    500   switch (hTpEnc->transportFmt) {
    501     case TT_MP4_LATM_MCP0:
    502     case TT_MP4_LATM_MCP1:
    503     case TT_MP4_LOAS:
    504       *nbytes = hTpEnc->bsBufferSize;
    505       tpErr = transportEnc_LatmGetFrame(&hTpEnc->writer.latm, hBs, nbytes);
    506       break;
    507     case TT_MP4_ADTS:
    508       if (hTpEnc->writer.adts.currentBlock >=
    509           hTpEnc->writer.adts.num_raw_blocks + 1) {
    510         *nbytes = (FDKgetValidBits(hBs) + 7) >> 3;
    511         hTpEnc->writer.adts.currentBlock = 0;
    512       } else {
    513         *nbytes = 0;
    514       }
    515       break;
    516     case TT_MP4_ADIF:
    517       FDK_ASSERT((INT)FDKgetValidBits(hBs) >= 0);
    518       *nbytes = (FDKgetValidBits(hBs) + 7) >> 3;
    519       break;
    520     case TT_MP4_RAW:
    521       FDKsyncCache(hBs);
    522       hTpEnc->writer.raw.curSubFrame++;
    523       *nbytes = ((FDKgetValidBits(hBs) - hTpEnc->writer.raw.prevBits) + 7) >> 3;
    524       break;
    525     default:
    526       break;
    527   }
    528 
    529   return tpErr;
    530 }
    531 
    532 INT transportEnc_GetStaticBits(HANDLE_TRANSPORTENC hTp, int auBits) {
    533   INT nbits = 0, nPceBits = 0;
    534 
    535   /* Write PCE within raw_data_block in transport lib. */
    536   if (hTp->pceFrameCounter >= hTp->config.headerPeriod) {
    537     nPceBits = transportEnc_GetPCEBits(
    538         hTp->config.channelMode, hTp->config.matrixMixdownA,
    539         3);             /* Consider 3 bits ID signalling in alignment */
    540     auBits += nPceBits; /* Adapt required raw_data_block bit consumtpion for AU
    541                            length information e.g. in LATM/LOAS configuration.
    542                          */
    543   }
    544 
    545   switch (hTp->transportFmt) {
    546     case TT_MP4_ADIF:
    547     case TT_MP4_RAW:
    548       nbits = 0; /* Do not consider the ADIF header into the total bitrate */
    549       break;
    550     case TT_MP4_ADTS:
    551       nbits = adtsWrite_GetHeaderBits(&hTp->writer.adts);
    552       break;
    553     case TT_MP4_LOAS:
    554     case TT_MP4_LATM_MCP0:
    555     case TT_MP4_LATM_MCP1:
    556       nbits =
    557           transportEnc_LatmCountTotalBitDemandHeader(&hTp->writer.latm, auBits);
    558       break;
    559     default:
    560       nbits = 0;
    561       break;
    562   }
    563 
    564   /* PCE is written in the transport library therefore the bit consumption is
    565    * part of the transport static bits. */
    566   nbits += nPceBits;
    567 
    568   return nbits;
    569 }
    570 
    571 void transportEnc_Close(HANDLE_TRANSPORTENC *phTp) {
    572   if (phTp != NULL) {
    573     if (*phTp != NULL) {
    574       FreeRam_TransportEncoder(phTp);
    575     }
    576   }
    577 }
    578 
    579 int transportEnc_CrcStartReg(HANDLE_TRANSPORTENC hTpEnc, int mBits) {
    580   int crcReg = 0;
    581 
    582   switch (hTpEnc->transportFmt) {
    583     case TT_MP4_ADTS:
    584       crcReg = adtsWrite_CrcStartReg(&hTpEnc->writer.adts, &hTpEnc->bitStream,
    585                                      mBits);
    586       break;
    587     default:
    588       break;
    589   }
    590 
    591   return crcReg;
    592 }
    593 
    594 void transportEnc_CrcEndReg(HANDLE_TRANSPORTENC hTpEnc, int reg) {
    595   switch (hTpEnc->transportFmt) {
    596     case TT_MP4_ADTS:
    597       adtsWrite_CrcEndReg(&hTpEnc->writer.adts, &hTpEnc->bitStream, reg);
    598       break;
    599     default:
    600       break;
    601   }
    602 }
    603 
    604 TRANSPORTENC_ERROR transportEnc_GetConf(HANDLE_TRANSPORTENC hTpEnc,
    605                                         CODER_CONFIG *cc,
    606                                         FDK_BITSTREAM *dataBuffer,
    607                                         UINT *confType) {
    608   TRANSPORTENC_ERROR tpErr = TRANSPORTENC_OK;
    609   HANDLE_LATM_STREAM hLatmConfig = &hTpEnc->writer.latm;
    610 
    611   *confType = 0; /* set confType variable to default */
    612 
    613   /* write StreamMuxConfig or AudioSpecificConfig depending on format used */
    614   switch (hTpEnc->transportFmt) {
    615     case TT_MP4_LATM_MCP0:
    616     case TT_MP4_LATM_MCP1:
    617     case TT_MP4_LOAS:
    618       tpErr =
    619           CreateStreamMuxConfig(hLatmConfig, dataBuffer, 0, &hTpEnc->callbacks);
    620       *confType = 1; /* config is SMC */
    621       break;
    622     default:
    623       if (transportEnc_writeASC(dataBuffer, cc, &hTpEnc->callbacks) != 0) {
    624         tpErr = TRANSPORTENC_UNKOWN_ERROR;
    625       }
    626   }
    627 
    628   return tpErr;
    629 }
    630 
    631 TRANSPORTENC_ERROR transportEnc_GetLibInfo(LIB_INFO *info) {
    632   int i;
    633 
    634   if (info == NULL) {
    635     return TRANSPORTENC_INVALID_PARAMETER;
    636   }
    637   /* search for next free tab */
    638   for (i = 0; i < FDK_MODULE_LAST; i++) {
    639     if (info[i].module_id == FDK_NONE) break;
    640   }
    641   if (i == FDK_MODULE_LAST) {
    642     return TRANSPORTENC_UNKOWN_ERROR;
    643   }
    644   info += i;
    645 
    646   info->module_id = FDK_TPENC;
    647   info->version = LIB_VERSION(TP_LIB_VL0, TP_LIB_VL1, TP_LIB_VL2);
    648   LIB_VERSION_STRING(info);
    649 #ifdef __ANDROID__
    650   info->build_date = "";
    651   info->build_time = "";
    652 #else
    653   info->build_date = __DATE__;
    654   info->build_time = __TIME__;
    655 #endif
    656   info->title = TP_LIB_TITLE;
    657 
    658   /* Set flags */
    659   info->flags =
    660       0 | CAPF_ADIF | CAPF_ADTS | CAPF_LATM | CAPF_LOAS | CAPF_RAWPACKETS;
    661 
    662   return TRANSPORTENC_OK;
    663 }
    664