Home | History | Annotate | Download | only in src
      1 
      2 /* -----------------------------------------------------------------------------------------------------------
      3 Software License for The Fraunhofer FDK AAC Codec Library for Android
      4 
      5  Copyright  1995 - 2012 Fraunhofer-Gesellschaft zur Frderung der angewandten Forschung e.V.
      6   All rights reserved.
      7 
      8  1.    INTRODUCTION
      9 The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements
     10 the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio.
     11 This FDK AAC Codec software is intended to be used on a wide variety of Android devices.
     12 
     13 AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual
     14 audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by
     15 independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part
     16 of the MPEG specifications.
     17 
     18 Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer)
     19 may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners
     20 individually for the purpose of encoding or decoding bit streams in products that are compliant with
     21 the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license
     22 these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec
     23 software may already be covered under those patent licenses when it is used for those licensed purposes only.
     24 
     25 Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality,
     26 are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional
     27 applications information and documentation.
     28 
     29 2.    COPYRIGHT LICENSE
     30 
     31 Redistribution and use in source and binary forms, with or without modification, are permitted without
     32 payment of copyright license fees provided that you satisfy the following conditions:
     33 
     34 You must retain the complete text of this software license in redistributions of the FDK AAC Codec or
     35 your modifications thereto in source code form.
     36 
     37 You must retain the complete text of this software license in the documentation and/or other materials
     38 provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form.
     39 You must make available free of charge copies of the complete source code of the FDK AAC Codec and your
     40 modifications thereto to recipients of copies in binary form.
     41 
     42 The name of Fraunhofer may not be used to endorse or promote products derived from this library without
     43 prior written permission.
     44 
     45 You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec
     46 software or your modifications thereto.
     47 
     48 Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software
     49 and the date of any change. For modified versions of the FDK AAC Codec, the term
     50 "Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term
     51 "Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android."
     52 
     53 3.    NO PATENT LICENSE
     54 
     55 NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer,
     56 ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with
     57 respect to this software.
     58 
     59 You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized
     60 by appropriate patent licenses.
     61 
     62 4.    DISCLAIMER
     63 
     64 This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors
     65 "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties
     66 of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
     67 CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages,
     68 including but not limited to procurement of substitute goods or services; loss of use, data, or profits,
     69 or business interruption, however caused and on any theory of liability, whether in contract, strict
     70 liability, or tort (including negligence), arising in any way out of the use of this software, even if
     71 advised of the possibility of such damage.
     72 
     73 5.    CONTACT INFORMATION
     74 
     75 Fraunhofer Institute for Integrated Circuits IIS
     76 Attention: Audio and Multimedia Departments - FDK AAC LL
     77 Am Wolfsmantel 33
     78 91058 Erlangen, Germany
     79 
     80 www.iis.fraunhofer.de/amm
     81 amm-info (at) iis.fraunhofer.de
     82 ----------------------------------------------------------------------------------------------------------- */
     83 
     84 /**************************  MPEG-4 Transport Decoder  ************************
     85 
     86    Author(s): Manuel Jander
     87    Description: MPEG Transport decoder
     88 
     89 ******************************************************************************/
     90 
     91 #include "tpdec_lib.h"
     92 
     93 /* library version */
     94 #include "version"
     95 
     96 
     97 #include "tp_data.h"
     98 
     99 #include "tpdec_adts.h"
    100 
    101 #include "tpdec_adif.h"
    102 
    103 #include "tpdec_latm.h"
    104 
    105 
    106 
    107 #define MODULE_NAME "transportDec"
    108 
    109 typedef union {
    110   STRUCT_ADTS adts;
    111 
    112   CAdifHeader adif;
    113 
    114   CLatmDemux latm;
    115 
    116 
    117 } transportdec_parser_t;
    118 
    119 struct TRANSPORTDEC
    120 {
    121   TRANSPORT_TYPE transportFmt;     /*!< MPEG4 transportDec type. */
    122 
    123   CSTpCallBacks callbacks;         /*!< Struct holding callback and its data */
    124 
    125   FDK_BITSTREAM bitStream[2]; /* Bitstream reader */
    126   UCHAR *bsBuffer;                 /* Internal bitstreamd data buffer (unallocated in case of TT_MP4_RAWPACKETS) */
    127 
    128   transportdec_parser_t parser;    /* Format specific parser structs. */
    129 
    130   CSAudioSpecificConfig asc[(1*2)]; /* Audio specific config from the last config found. */
    131   UINT  globalFramePos;            /* Global transport frame reference bit position. */
    132   UINT  accessUnitAnchor[2];    /* Current access unit start bit position. */
    133   INT   auLength[2];            /* Length of current access unit. */
    134   INT   numberOfRawDataBlocks;     /* Current number of raw data blocks contained remaining from the current transport frame. */
    135   UINT  avgBitRate;                /* Average bit rate used for frame loss estimation. */
    136   UINT  lastValidBufferFullness;   /* Last valid buffer fullness value for frame loss estimation */
    137   INT   remainder;                 /* Reminder in division during lost access unit estimation. */
    138   INT   missingAccessUnits;        /* Estimated missing access units. */
    139   UINT  burstPeriod;               /* Data burst period in mili seconds. */
    140   UINT  holdOffFrames;             /* Amount of frames that were already hold off due to buffer fullness condition not being met. */
    141   UINT  flags;                     /* Flags. */
    142 };
    143 
    144 /* Flag bitmasks for "flags" member of struct TRANSPORTDEC */
    145 #define TPDEC_SYNCOK                1
    146 #define TPDEC_MINIMIZE_DELAY        2
    147 #define TPDEC_IGNORE_BUFFERFULLNESS 4
    148 #define TPDEC_EARLY_CONFIG          8
    149 #define TPDEC_LOST_FRAMES_PENDING  16
    150 #define TPDEC_CONFIG_FOUND         32
    151 
    152 C_ALLOC_MEM(Ram_TransportDecoder, TRANSPORTDEC, 1)
    153 C_ALLOC_MEM(Ram_TransportDecoderBuffer, UCHAR, TRANSPORTDEC_INBUF_SIZE)
    154 
    155 
    156 
    157 
    158 HANDLE_TRANSPORTDEC transportDec_Open( const TRANSPORT_TYPE transportFmt, const UINT flags)
    159 {
    160   HANDLE_TRANSPORTDEC hInput;
    161 
    162   hInput = GetRam_TransportDecoder(0);
    163   if ( hInput == NULL ) {
    164     return NULL;
    165   }
    166 
    167   /* Init transportDec struct. */
    168   hInput->transportFmt = transportFmt;
    169 
    170   switch (transportFmt) {
    171 
    172   case TT_MP4_ADIF:
    173     break;
    174 
    175   case TT_MP4_ADTS:
    176     if (flags & TP_FLAG_MPEG4)
    177       hInput->parser.adts.decoderCanDoMpeg4 = 1;
    178     else
    179       hInput->parser.adts.decoderCanDoMpeg4 = 0;
    180     adtsRead_CrcInit(&hInput->parser.adts);
    181     hInput->parser.adts.BufferFullnesStartFlag = 1;
    182     hInput->numberOfRawDataBlocks = 0;
    183     break;
    184 
    185 
    186   case TT_MP4_LATM_MCP0:
    187   case TT_MP4_LATM_MCP1:
    188   case TT_MP4_LOAS:
    189   case TT_MP4_RAW:
    190     break;
    191 
    192   default:
    193     FreeRam_TransportDecoder(&hInput);
    194     hInput = NULL;
    195     break;
    196   }
    197 
    198   if (hInput != NULL) {
    199     /* Create bitstream */
    200     if ( (transportFmt == TT_MP4_RAW)
    201       || (transportFmt == TT_DRM) ){
    202       hInput->bsBuffer = NULL;
    203     } else {
    204       hInput->bsBuffer = GetRam_TransportDecoderBuffer(0);
    205       if (hInput->bsBuffer == NULL) {
    206           transportDec_Close( &hInput );
    207           return NULL;
    208       }
    209       FDKinitBitStream(&hInput->bitStream[0], hInput->bsBuffer, TRANSPORTDEC_INBUF_SIZE, 0, BS_READER);
    210     }
    211 
    212     hInput->burstPeriod = 0;
    213   }
    214 
    215   return hInput;
    216 }
    217 
    218 TRANSPORTDEC_ERROR transportDec_OutOfBandConfig(HANDLE_TRANSPORTDEC hTp, UCHAR *conf, const UINT length, UINT layer )
    219 {
    220   TRANSPORTDEC_ERROR     err        = TRANSPORTDEC_OK;
    221 
    222   FDK_BITSTREAM bs;
    223   HANDLE_FDK_BITSTREAM  hBs        = &bs;
    224 
    225   FDKinitBitStream(hBs, conf, 0x80000000, length<<3, BS_READER);
    226 
    227   /* config transport decoder */
    228   switch (hTp->transportFmt) {
    229     case TT_MP4_LATM_MCP0:
    230     case TT_MP4_LATM_MCP1:
    231     case TT_MP4_LOAS:
    232       {
    233         if (layer != 0) {
    234           return TRANSPORTDEC_INVALID_PARAMETER;
    235         }
    236         CLatmDemux *pLatmDemux = &hTp->parser.latm;
    237         err = CLatmDemux_ReadStreamMuxConfig(hBs, pLatmDemux, &hTp->callbacks, hTp->asc);
    238         if (err != TRANSPORTDEC_OK) {
    239           return err;
    240         }
    241       }
    242       break;
    243     default:
    244     case TT_MP4_RAW:
    245       err = AudioSpecificConfig_Parse(&hTp->asc[layer], hBs, 1, &hTp->callbacks);
    246       break;
    247   }
    248   if (err == TRANSPORTDEC_OK) {
    249     int errC;
    250 
    251     errC = hTp->callbacks.cbUpdateConfig(hTp->callbacks.cbUpdateConfigData, &hTp->asc[layer]);
    252     if (errC != 0) {
    253       err = TRANSPORTDEC_PARSE_ERROR;
    254     }
    255   }
    256 
    257   if (err == TRANSPORTDEC_OK) {
    258     hTp->flags |= TPDEC_CONFIG_FOUND;
    259   }
    260 
    261   return err;
    262 }
    263 
    264 int transportDec_RegisterAscCallback( HANDLE_TRANSPORTDEC hTpDec, const cbUpdateConfig_t cbUpdateConfig, void* user_data)
    265 {
    266   if (hTpDec == NULL) {
    267     return -1;
    268   }
    269   hTpDec->callbacks.cbUpdateConfig = cbUpdateConfig;
    270   hTpDec->callbacks.cbUpdateConfigData = user_data;
    271   return 0;
    272 }
    273 
    274 int transportDec_RegisterSscCallback( HANDLE_TRANSPORTDEC hTpDec, const cbSsc_t cbSsc, void* user_data)
    275 {
    276   if (hTpDec == NULL) {
    277     return -1;
    278   }
    279   hTpDec->callbacks.cbSsc = cbSsc;
    280   hTpDec->callbacks.cbSscData = user_data;
    281   return 0;
    282 }
    283 
    284 int transportDec_RegisterSbrCallback( HANDLE_TRANSPORTDEC hTpDec, const cbSbr_t cbSbr, void* user_data)
    285 {
    286   if (hTpDec == NULL) {
    287     return -1;
    288   }
    289   hTpDec->callbacks.cbSbr = cbSbr;
    290   hTpDec->callbacks.cbSbrData = user_data;
    291   return 0;
    292 }
    293 
    294 TRANSPORTDEC_ERROR transportDec_FillData(
    295         const HANDLE_TRANSPORTDEC  hTp,
    296         UCHAR                     *pBuffer,
    297         const UINT                 bufferSize,
    298         UINT                      *pBytesValid,
    299         const INT                  layer )
    300 {
    301   HANDLE_FDK_BITSTREAM hBs;
    302 
    303   if ( (hTp == NULL)
    304     || (layer >= 2) ) {
    305     return TRANSPORTDEC_INVALID_PARAMETER;
    306   }
    307 
    308   if (*pBytesValid == 0) {
    309     /* nothing to do */
    310     return TRANSPORTDEC_OK;
    311   }
    312 
    313   /* set bitbuffer shortcut */
    314   hBs = &hTp->bitStream[layer];
    315 
    316   switch (hTp->transportFmt) {
    317   case TT_MP4_RAW:
    318   case TT_DRM:
    319     /* For packet based transport, pass input buffer to bitbuffer without copying the data.
    320        Unfortunately we do not know the actual buffer size. And the FDK bit buffer implementation
    321        needs a number 2^x. So we assume the maximum of 48 channels with 6144 bits per channel
    322        and round it up to the next power of 2 => 65536 bytes */
    323     FDKinitBitStream(hBs, pBuffer, 0x10000, (*pBytesValid)<<3, BS_READER);
    324     *pBytesValid = 0;
    325     break;
    326 
    327   default:
    328     /* ... else feed bitbuffer with new stream data (append). */
    329     if (hTp->numberOfRawDataBlocks <= 0) {
    330       FDKfeedBuffer (hBs, pBuffer, bufferSize, pBytesValid) ;
    331     }
    332   }
    333 
    334   return TRANSPORTDEC_OK;
    335 }
    336 
    337 HANDLE_FDK_BITSTREAM transportDec_GetBitstream( const HANDLE_TRANSPORTDEC hTp, const UINT layer )
    338 {
    339   return &hTp->bitStream[layer];
    340 }
    341 
    342 TRANSPORT_TYPE transportDec_GetFormat( const HANDLE_TRANSPORTDEC hTp )
    343 {
    344   return hTp->transportFmt;
    345 }
    346 
    347 INT transportDec_GetBufferFullness( const HANDLE_TRANSPORTDEC hTp )
    348 {
    349   INT bufferFullness = -1;
    350 
    351   switch (hTp->transportFmt) {
    352     case TT_MP4_ADTS:
    353       if (hTp->parser.adts.bs.adts_fullness != 0x7ff) {
    354         bufferFullness = hTp->parser.adts.bs.frame_length*8 + hTp->parser.adts.bs.adts_fullness * 32 * getNumberOfEffectiveChannels(hTp->parser.adts.bs.channel_config);
    355       }
    356       break;
    357     case TT_MP4_LOAS:
    358     case TT_MP4_LATM_MCP0:
    359     case TT_MP4_LATM_MCP1:
    360       if (hTp->parser.latm.m_linfo[0][0].m_bufferFullness != 0xff) {
    361         bufferFullness = hTp->parser.latm.m_linfo[0][0].m_bufferFullness;
    362       }
    363       break;
    364     default:
    365       break;
    366   }
    367 
    368   return bufferFullness;
    369 }
    370 
    371 /**
    372  * \brief Determine additional buffer fullness contraint due to burst data reception.
    373  *        The parameter TPDEC_PARAM_BURSTPERIOD must have been set as a precondition.
    374  * \param hTp transport decoder handle.
    375  * \param bufferFullness the buffer fullness value of the first frame to be decoded.
    376  * \param bitsAvail the amount of available bits at the end of the first frame to be decoded.
    377  * \return error code
    378  */
    379 static
    380 TRANSPORTDEC_ERROR additionalHoldOffNeeded(
    381         HANDLE_TRANSPORTDEC hTp,
    382         INT                 bufferFullness,
    383         INT                 bitsAvail
    384         )
    385 {
    386   INT checkLengthBits, avgBitsPerFrame;
    387   INT maxAU; /* maximum number of frames per Master Frame */
    388   INT samplesPerFrame = hTp->asc->m_samplesPerFrame;
    389   INT samplingFrequency = (INT)hTp->asc->m_samplingFrequency;
    390 
    391   if ( (hTp->avgBitRate == 0) || (hTp->burstPeriod == 0) ) {
    392     return TRANSPORTDEC_OK;
    393   }
    394   if ( (samplesPerFrame == 0 ) || (samplingFrequency == 0) ) {
    395     return TRANSPORTDEC_NOT_ENOUGH_BITS;
    396   }
    397 
    398   /* One Master Frame is sent every hTp->burstPeriod ms */
    399   maxAU = hTp->burstPeriod * samplingFrequency + (samplesPerFrame*1000 - 1);
    400   maxAU = maxAU / (samplesPerFrame*1000);
    401   /* Subtract number of frames which were already held off. */
    402   maxAU -= hTp->holdOffFrames;
    403 
    404   avgBitsPerFrame = hTp->avgBitRate * samplesPerFrame + (samplingFrequency-1);
    405   avgBitsPerFrame = avgBitsPerFrame / samplingFrequency;
    406 
    407   /* Consider worst case of bufferFullness quantization. */
    408   switch (hTp->transportFmt) {
    409     case TT_MP4_ADIF:
    410     case TT_MP4_ADTS:
    411     case TT_MP4_LOAS:
    412     case TT_MP4_LATM_MCP0:
    413     case TT_MP4_LATM_MCP1:
    414       bufferFullness += 31;
    415       break;
    416     default:
    417       break;
    418   }
    419 
    420   checkLengthBits = bufferFullness + (maxAU-1)*avgBitsPerFrame;
    421 
    422   /* Check if buffer is big enough to fullfill buffer fullness condition */
    423   if ( (checkLengthBits /*+headerBits*/) > ((TRANSPORTDEC_INBUF_SIZE<<3)-7) ) {
    424     return TRANSPORTDEC_SYNC_ERROR;
    425   }
    426 
    427   if ( bitsAvail < checkLengthBits ) {
    428     return TRANSPORTDEC_NOT_ENOUGH_BITS;
    429   }
    430   else {
    431     return TRANSPORTDEC_OK;
    432   }
    433 }
    434 
    435 /**
    436  * \brief adjust bit stream position and the end of an access unit.
    437  * \param hTp transport decoder handle.
    438  * \return error code.
    439  */
    440 static
    441 TRANSPORTDEC_ERROR transportDec_AdjustEndOfAccessUnit(HANDLE_TRANSPORTDEC hTp)
    442 {
    443   HANDLE_FDK_BITSTREAM hBs = &hTp->bitStream[0];
    444   TRANSPORTDEC_ERROR err = TRANSPORTDEC_OK;
    445 
    446   switch (hTp->transportFmt) {
    447     case TT_MP4_LOAS:
    448     case TT_MP4_LATM_MCP0:
    449     case TT_MP4_LATM_MCP1:
    450       if ( hTp->numberOfRawDataBlocks == 0 )
    451       {
    452         /* Check global frame length */
    453         if (hTp->transportFmt == TT_MP4_LOAS && hTp->parser.latm.m_audioMuxLengthBytes > 0)
    454         {
    455           int loasOffset;
    456 
    457           loasOffset = (hTp->parser.latm.m_audioMuxLengthBytes*8 + FDKgetValidBits(hBs)) - hTp->globalFramePos;
    458           if (loasOffset != 0) {
    459             FDKpushBiDirectional(hBs, loasOffset);
    460             /* For ELD and other payloads there is an unknown amount of padding, so ignore unread bits, but
    461                throw an error only if too many bits where read. */
    462             if (loasOffset < 0) {
    463               err = TRANSPORTDEC_PARSE_ERROR;
    464             }
    465           }
    466         }
    467 
    468         /* Do global LOAS/LATM audioMuxElement byte alignment */
    469         FDKbyteAlign(hBs, hTp->globalFramePos);
    470       }
    471       break;
    472     default:
    473       break;
    474   }
    475 
    476   return err;
    477 }
    478 
    479 
    480 /* How many bits to advance for synchronization search. */
    481 #define TPDEC_SYNCSKIP 8
    482 
    483 static
    484 TRANSPORTDEC_ERROR synchronization(
    485         HANDLE_TRANSPORTDEC hTp,
    486         INT                *pHeaderBits
    487         )
    488 {
    489   TRANSPORTDEC_ERROR err = TRANSPORTDEC_OK, errFirstFrame = TRANSPORTDEC_OK;
    490   HANDLE_FDK_BITSTREAM hBs = &hTp->bitStream[0];
    491 
    492   INT syncLayerFrameBits = 0; /* Length of sync layer frame (i.e. LOAS) */
    493   INT rawDataBlockLength = 0, rawDataBlockLengthPrevious;
    494   INT totalBits;
    495   INT headerBits = 0, headerBitsFirstFrame = 0, headerBitsPrevious;
    496   INT numFramesTraversed = 0, fTraverseMoreFrames, fConfigFound = 0, startPos, startPosFirstFrame = -1;
    497   INT numRawDataBlocksFirstFrame = 0, numRawDataBlocksPrevious, globalFramePosFirstFrame = 0, rawDataBlockLengthFirstFrame = 0;
    498   INT ignoreBufferFullness = hTp->flags & (TPDEC_IGNORE_BUFFERFULLNESS|TPDEC_SYNCOK);
    499 
    500   /* Synch parameters */
    501   INT syncLength;      /* Length of sync word in bits */
    502   UINT syncWord;       /* Sync word to be found */
    503   UINT syncMask;       /* Mask for sync word (for adding one bit, so comprising one bit less) */
    504   C_ALLOC_SCRATCH_START(contextFirstFrame, transportdec_parser_t, 1);
    505 
    506   totalBits = (INT)FDKgetValidBits(hBs);
    507 
    508   if (totalBits <= 0) {
    509     /* Return sync error, because this happens only in case of severly damaged bit streams.
    510        Returning TRANSPORTDEC_NOT_ENOUGH_BITS here is very dangerous. */
    511     /* numberOfRawDataBlocks must be always reset in case of sync errors. */
    512     hTp->numberOfRawDataBlocks = 0;
    513     goto bail;
    514   }
    515 
    516   fTraverseMoreFrames = (hTp->flags & (TPDEC_MINIMIZE_DELAY|TPDEC_EARLY_CONFIG)) && ! (hTp->flags & TPDEC_SYNCOK);
    517 
    518   /* Set transport specific sync parameters */
    519   switch (hTp->transportFmt) {
    520     case TT_MP4_ADTS:
    521       syncWord = ADTS_SYNCWORD;
    522       syncLength = ADTS_SYNCLENGTH;
    523       break;
    524     case TT_MP4_LOAS:
    525       syncWord = 0x2B7;
    526       syncLength = 11;
    527       break;
    528     default:
    529       syncWord = 0;
    530       syncLength = 0;
    531       break;
    532   }
    533 
    534   syncMask = (1<<syncLength)-1;
    535 
    536   do {
    537     INT bitsAvail = 0;     /* Bits available in bitstream buffer    */
    538     INT checkLengthBits;   /* Helper to check remaining bits and buffer boundaries */
    539     UINT synch;            /* Current sync word read from bitstream */
    540 
    541     headerBitsPrevious = headerBits;
    542 
    543     bitsAvail = (INT)FDKgetValidBits(hBs);
    544 
    545     if (hTp->numberOfRawDataBlocks == 0) {
    546       /* search synchword */
    547 
    548       FDK_ASSERT( (bitsAvail % TPDEC_SYNCSKIP) == 0);
    549 
    550       if ((bitsAvail-syncLength) < TPDEC_SYNCSKIP) {
    551         err = TRANSPORTDEC_NOT_ENOUGH_BITS;
    552         headerBits = 0;
    553       } else {
    554 
    555         synch = FDKreadBits(hBs, syncLength);
    556 
    557         if ( !(hTp->flags & TPDEC_SYNCOK) ) {
    558           for (; (bitsAvail-syncLength) >= TPDEC_SYNCSKIP; bitsAvail-=TPDEC_SYNCSKIP) {
    559             if (synch == syncWord) {
    560               break;
    561             }
    562             synch = ((synch << TPDEC_SYNCSKIP) & syncMask) | FDKreadBits(hBs, TPDEC_SYNCSKIP);
    563           }
    564         }
    565         if (synch != syncWord) {
    566           /* No correct syncword found. */
    567           err = TRANSPORTDEC_SYNC_ERROR;
    568         } else {
    569           err = TRANSPORTDEC_OK;
    570         }
    571         headerBits = syncLength;
    572       }
    573     } else {
    574       headerBits = 0;
    575     }
    576 
    577     /* Save previous raw data block data */
    578     rawDataBlockLengthPrevious = rawDataBlockLength;
    579     numRawDataBlocksPrevious = hTp->numberOfRawDataBlocks;
    580 
    581     /* Parse transport header (raw data block granularity) */
    582     startPos = FDKgetValidBits(hBs);
    583 
    584     if (err == TRANSPORTDEC_OK )
    585     {
    586       switch (hTp->transportFmt) {
    587         case TT_MP4_ADTS:
    588           if (hTp->numberOfRawDataBlocks <= 0)
    589           {
    590             int errC;
    591 
    592             /* Parse ADTS header */
    593             err = adtsRead_DecodeHeader( &hTp->parser.adts, &hTp->asc[0], hBs, ignoreBufferFullness );
    594             if (err != TRANSPORTDEC_OK) {
    595               if (err != TRANSPORTDEC_NOT_ENOUGH_BITS) {
    596                 err = TRANSPORTDEC_SYNC_ERROR;
    597               }
    598             } else {
    599               errC = hTp->callbacks.cbUpdateConfig(hTp->callbacks.cbUpdateConfigData, &hTp->asc[0]);
    600               if (errC != 0) {
    601                 err = TRANSPORTDEC_SYNC_ERROR;
    602               } else {
    603                 hTp->numberOfRawDataBlocks = hTp->parser.adts.bs.num_raw_blocks+1;
    604                 /* CAUTION: The PCE (if available) is declared to be a part of the header! */
    605                 hTp->globalFramePos = FDKgetValidBits(hBs) + hTp->parser.adts.bs.num_pce_bits;
    606               }
    607             }
    608           }
    609           else {
    610             /* Reset CRC because the next bits are the beginning of a raw_data_block() */
    611             FDKcrcReset(&hTp->parser.adts.crcInfo);
    612             hTp->globalFramePos = FDKgetValidBits(hBs);
    613           }
    614           if (err == TRANSPORTDEC_OK) {
    615             hTp->numberOfRawDataBlocks--;
    616             rawDataBlockLength = adtsRead_GetRawDataBlockLength(&hTp->parser.adts, (hTp->parser.adts.bs.num_raw_blocks-hTp->numberOfRawDataBlocks));
    617             syncLayerFrameBits = (hTp->parser.adts.bs.frame_length<<3) - (startPos - FDKgetValidBits(hBs)) - syncLength;
    618             if (syncLayerFrameBits <= 0) {
    619               err = TRANSPORTDEC_SYNC_ERROR;
    620             }
    621           } else {
    622             hTp->numberOfRawDataBlocks = 0;
    623           }
    624           break;
    625         case TT_MP4_LOAS:
    626           if (hTp->numberOfRawDataBlocks <= 0)
    627           {
    628             syncLayerFrameBits = FDKreadBits(hBs, 13);
    629             hTp->parser.latm.m_audioMuxLengthBytes = syncLayerFrameBits;
    630             syncLayerFrameBits <<= 3;
    631           }
    632         case TT_MP4_LATM_MCP1:
    633         case TT_MP4_LATM_MCP0:
    634           if (hTp->numberOfRawDataBlocks <= 0)
    635           {
    636             hTp->globalFramePos = FDKgetValidBits(hBs);
    637 
    638             err = CLatmDemux_Read(
    639                     hBs,
    640                    &hTp->parser.latm,
    641                     hTp->transportFmt,
    642                    &hTp->callbacks,
    643                     hTp->asc,
    644                     ignoreBufferFullness);
    645 
    646             if (err != TRANSPORTDEC_OK) {
    647               if (err != TRANSPORTDEC_NOT_ENOUGH_BITS) {
    648                 err = TRANSPORTDEC_SYNC_ERROR;
    649               }
    650             } else {
    651               hTp->numberOfRawDataBlocks = CLatmDemux_GetNrOfSubFrames(&hTp->parser.latm);
    652               syncLayerFrameBits -= startPos - FDKgetValidBits(hBs) - (13);
    653             }
    654           } else {
    655             err = CLatmDemux_ReadPayloadLengthInfo(hBs, &hTp->parser.latm);
    656             if (err != TRANSPORTDEC_OK) {
    657               err = TRANSPORTDEC_SYNC_ERROR;
    658             }
    659           }
    660           if (err == TRANSPORTDEC_OK) {
    661             rawDataBlockLength = CLatmDemux_GetFrameLengthInBits(&hTp->parser.latm);
    662             hTp->numberOfRawDataBlocks--;
    663           } else {
    664             hTp->numberOfRawDataBlocks = 0;
    665           }
    666           break;
    667         default:
    668           {
    669             syncLayerFrameBits = 0;
    670           }
    671           break;
    672       }
    673     }
    674 
    675     headerBits += startPos - (INT)FDKgetValidBits(hBs);
    676     bitsAvail -= headerBits;
    677 
    678     checkLengthBits  = syncLayerFrameBits;
    679 
    680     /* Check if the whole frame would fit the bitstream buffer */
    681     if (err == TRANSPORTDEC_OK) {
    682       if ( (checkLengthBits+headerBits) > ((TRANSPORTDEC_INBUF_SIZE<<3)-7) ) {
    683         /* We assume that the size of the transport bit buffer has been
    684            chosen to meet all system requirements, thus this condition
    685            is considered a synchronisation error. */
    686         err = TRANSPORTDEC_SYNC_ERROR;
    687       } else {
    688         if ( bitsAvail < checkLengthBits ) {
    689           err = TRANSPORTDEC_NOT_ENOUGH_BITS;
    690         }
    691       }
    692     }
    693 
    694     if (err == TRANSPORTDEC_NOT_ENOUGH_BITS) {
    695       break;
    696     }
    697 
    698 
    699     if (err == TRANSPORTDEC_SYNC_ERROR) {
    700       int bits;
    701 
    702       /* Enforce re-sync of transport headers. */
    703       hTp->numberOfRawDataBlocks = 0;
    704 
    705       /* Ensure that the bit amount lands and a multiple of TPDEC_SYNCSKIP */
    706       bits = (bitsAvail + headerBits) % TPDEC_SYNCSKIP;
    707       /* Rewind - TPDEC_SYNCSKIP, in order to look for a synch one bit ahead next time. */
    708       FDKpushBiDirectional(hBs, -(headerBits - TPDEC_SYNCSKIP) + bits);
    709       bitsAvail += headerBits - TPDEC_SYNCSKIP - bits;
    710       headerBits = 0;
    711     }
    712 
    713     /* Frame traversal */
    714     if ( fTraverseMoreFrames )
    715     {
    716       /* Save parser context for early config discovery "rewind all frames" */
    717       if ( (hTp->flags & TPDEC_EARLY_CONFIG) && !(hTp->flags & TPDEC_MINIMIZE_DELAY))
    718       {
    719         /* ignore buffer fullness if just traversing additional frames for ECD */
    720         ignoreBufferFullness = 1;
    721 
    722         /* Save context in order to return later */
    723         if ( err == TRANSPORTDEC_OK && startPosFirstFrame == -1 ) {
    724           startPosFirstFrame = FDKgetValidBits(hBs);
    725           numRawDataBlocksFirstFrame = hTp->numberOfRawDataBlocks;
    726           globalFramePosFirstFrame = hTp->globalFramePos;
    727           rawDataBlockLengthFirstFrame = rawDataBlockLength;
    728           headerBitsFirstFrame = headerBits;
    729           errFirstFrame = err;
    730           FDKmemcpy(contextFirstFrame, &hTp->parser, sizeof(transportdec_parser_t));
    731         }
    732 
    733         /* Break when config was found or it is not possible anymore to find a config */
    734         if (startPosFirstFrame != -1 && (fConfigFound || err != TRANSPORTDEC_OK)) {
    735           break;
    736         }
    737       }
    738 
    739       if (err == TRANSPORTDEC_OK) {
    740         FDKpushFor(hBs, rawDataBlockLength);
    741         bitsAvail -= rawDataBlockLength;
    742         numFramesTraversed++;
    743         /* Ignore error here itentionally. */
    744         transportDec_AdjustEndOfAccessUnit(hTp);
    745       }
    746     }
    747   } while ( fTraverseMoreFrames || (err == TRANSPORTDEC_SYNC_ERROR && !(hTp->flags & TPDEC_SYNCOK)));
    748 
    749   /* Restore context in case of ECD frame traversal */
    750   if ( startPosFirstFrame != -1 && (fConfigFound || err != TRANSPORTDEC_OK) ) {
    751     FDKpushBiDirectional(hBs, FDKgetValidBits(hBs) - startPosFirstFrame);
    752     FDKmemcpy(&hTp->parser, contextFirstFrame, sizeof(transportdec_parser_t));
    753     hTp->numberOfRawDataBlocks = numRawDataBlocksFirstFrame;
    754     hTp->globalFramePos = globalFramePosFirstFrame;
    755     rawDataBlockLength = rawDataBlockLengthFirstFrame;
    756     headerBits = headerBitsFirstFrame;
    757     err = errFirstFrame;
    758     numFramesTraversed = 0;
    759   }
    760 
    761   /* Additional burst data mode buffer fullness check. */
    762   if ( !(hTp->flags & (TPDEC_IGNORE_BUFFERFULLNESS|TPDEC_SYNCOK)) && err == TRANSPORTDEC_OK) {
    763     err = additionalHoldOffNeeded(hTp, transportDec_GetBufferFullness(hTp), FDKgetValidBits(hBs) - syncLayerFrameBits);
    764     if (err == TRANSPORTDEC_NOT_ENOUGH_BITS) {
    765       hTp->holdOffFrames++;
    766     }
    767   }
    768 
    769   /* Rewind for retry because of not enough bits */
    770   if (err == TRANSPORTDEC_NOT_ENOUGH_BITS) {
    771     FDKpushBack(hBs, headerBits);
    772     headerBits = 0;
    773   }
    774   else {
    775     /* reset hold off frame counter */
    776     hTp->holdOffFrames = 0;
    777   }
    778 
    779   /* Return to last good frame in case of frame traversal but not ECD. */
    780   if (numFramesTraversed > 0) {
    781     FDKpushBack(hBs, rawDataBlockLengthPrevious);
    782     if (err != TRANSPORTDEC_OK) {
    783       hTp->numberOfRawDataBlocks = numRawDataBlocksPrevious;
    784       headerBits = headerBitsPrevious;
    785     }
    786     err = TRANSPORTDEC_OK;
    787   }
    788 
    789 bail:
    790   hTp->auLength[0] = rawDataBlockLength;
    791 
    792   if (err == TRANSPORTDEC_OK) {
    793     hTp->flags |= TPDEC_SYNCOK;
    794   }
    795 
    796   if (pHeaderBits != NULL) {
    797     *pHeaderBits = headerBits;
    798   }
    799 
    800   if (err == TRANSPORTDEC_SYNC_ERROR) {
    801     hTp->flags &= ~TPDEC_SYNCOK;
    802   }
    803 
    804   C_ALLOC_SCRATCH_END(contextFirstFrame, transportdec_parser_t, 1);
    805 
    806   return err;
    807 }
    808 
    809 /**
    810  * \brief Synchronize to stream and estimate the amount of missing access units due
    811  *        to a current synchronization error in case of constant average bit rate.
    812  */
    813 static
    814 TRANSPORTDEC_ERROR transportDec_readStream ( HANDLE_TRANSPORTDEC hTp, const UINT layer )
    815 {
    816 
    817   TRANSPORTDEC_ERROR error = TRANSPORTDEC_OK;
    818   HANDLE_FDK_BITSTREAM hBs = &hTp->bitStream[layer];
    819   INT nAU = -1;
    820   INT headerBits;
    821   INT bitDistance, bfDelta;
    822 
    823   /* Obtain distance to next synch word */
    824   bitDistance = FDKgetValidBits(hBs);
    825   error = synchronization(hTp, &headerBits);
    826   bitDistance -= FDKgetValidBits(hBs);
    827 
    828 
    829   FDK_ASSERT(bitDistance >= 0);
    830 
    831   if (error == TRANSPORTDEC_SYNC_ERROR || (hTp->flags & TPDEC_LOST_FRAMES_PENDING))
    832   {
    833     /* Check if estimating lost access units is feasible. */
    834     if (hTp->avgBitRate > 0 && hTp->asc[0].m_samplesPerFrame > 0 && hTp->asc[0].m_samplingFrequency > 0)
    835     {
    836       if (error == TRANSPORTDEC_OK)
    837       {
    838         int aj;
    839 
    840         aj = transportDec_GetBufferFullness(hTp);
    841         if (aj > 0) {
    842           bfDelta = aj;
    843         } else {
    844           bfDelta = 0;
    845         }
    846         /* sync was ok: last of a series of bad access units. */
    847         hTp->flags &= ~TPDEC_LOST_FRAMES_PENDING;
    848         /* Add up bitDistance until end of the current frame. Later we substract
    849            this frame from the grand total, since this current successfully synchronized
    850            frame should not be skipped of course; but it must be accounted into the
    851            bufferfulness math. */
    852         bitDistance += hTp->auLength[0];
    853       } else {
    854         if ( !(hTp->flags & TPDEC_LOST_FRAMES_PENDING) ) {
    855           /* sync not ok: one of many bad access units. */
    856           hTp->flags |= TPDEC_LOST_FRAMES_PENDING;
    857           bfDelta = - (INT)hTp->lastValidBufferFullness;
    858         } else {
    859           bfDelta = 0;
    860         }
    861       }
    862 
    863       {
    864         int num, denom;
    865 
    866         /* Obtain estimate of number of lost frames */
    867         num = hTp->asc[0].m_samplingFrequency * (bfDelta + bitDistance) + hTp->remainder;
    868         denom = hTp->avgBitRate * hTp->asc[0].m_samplesPerFrame;
    869         if (num > 0) {
    870           nAU = num / denom;
    871           hTp->remainder = num % denom;
    872         } else {
    873           hTp->remainder = num;
    874         }
    875 
    876         if (error == TRANSPORTDEC_OK)
    877         {
    878           /* Final adjustment of remainder, taken -1 into account because current
    879              frame should not be skipped, thus substract -1 or do nothing instead
    880              of +1-1 accordingly. */
    881           if ( (denom - hTp->remainder) >= hTp->remainder ) {
    882             nAU--;
    883           }
    884 
    885           if (nAU < 0) {
    886             /* There was one frame too much concealed, so unfortunately we will have to skip one good frame. */
    887             transportDec_EndAccessUnit(hTp);
    888             error = synchronization(hTp, &headerBits);
    889             nAU = -1;
    890 #ifdef DEBUG
    891             FDKprintf("ERROR: Bufferfullness accounting failed. remainder=%d, nAU=%d\n", hTp->remainder, nAU);
    892 #endif
    893           }
    894           hTp->remainder = 0;
    895           /* Enforce last missed frames to be concealed. */
    896           if (nAU > 0) {
    897             FDKpushBack(hBs, headerBits);
    898           }
    899         }
    900       }
    901     }
    902   }
    903 
    904   /* Be sure that lost frames are handled correctly. This is necessary due to some
    905      sync error sequences where later it turns out that there is not enough data, but
    906      the bits upto the sync word are discarded, thus causing a value of nAU > 0 */
    907   if (nAU > 0) {
    908     error = TRANSPORTDEC_SYNC_ERROR;
    909   }
    910 
    911   hTp->missingAccessUnits = nAU;
    912 
    913   return error;
    914 }
    915 
    916 /* returns error code */
    917 TRANSPORTDEC_ERROR transportDec_ReadAccessUnit( const HANDLE_TRANSPORTDEC hTp, const UINT layer )
    918 {
    919   TRANSPORTDEC_ERROR err = TRANSPORTDEC_OK;
    920   HANDLE_FDK_BITSTREAM hBs;
    921 
    922   if (!hTp) {
    923     return TRANSPORTDEC_INVALID_PARAMETER;
    924   }
    925 
    926   hBs = &hTp->bitStream[layer];
    927 
    928   switch (hTp->transportFmt) {
    929 
    930     case TT_MP4_ADIF:
    931       /* Read header if not already done */
    932       if (!(hTp->flags & TPDEC_CONFIG_FOUND))
    933       {
    934         CProgramConfig *pce;
    935 
    936         AudioSpecificConfig_Init(&hTp->asc[0]);
    937         pce = &hTp->asc[0].m_progrConfigElement;
    938         err = adifRead_DecodeHeader(&hTp->parser.adif, pce, hBs);
    939         if (err)
    940           goto bail;
    941 
    942         /* Map adif header to ASC */
    943         hTp->asc[0].m_aot                    = (AUDIO_OBJECT_TYPE)(pce->Profile + 1);
    944         hTp->asc[0].m_samplingFrequencyIndex = pce->SamplingFrequencyIndex;
    945         hTp->asc[0].m_samplingFrequency      = SamplingRateTable[pce->SamplingFrequencyIndex];
    946         hTp->asc[0].m_channelConfiguration   = 0;
    947         hTp->asc[0].m_samplesPerFrame        = 1024;
    948         hTp->avgBitRate                      = hTp->parser.adif.BitRate;
    949 
    950         /* Call callback to decoder. */
    951         {
    952           int errC;
    953 
    954           errC = hTp->callbacks.cbUpdateConfig(hTp->callbacks.cbUpdateConfigData, &hTp->asc[0]);
    955           if (errC == 0) {
    956             hTp->flags |= TPDEC_CONFIG_FOUND;
    957           } else {
    958             err = TRANSPORTDEC_PARSE_ERROR;
    959             goto bail;
    960           }
    961         }
    962       }
    963       hTp->auLength[layer] = -1; /* Access Unit data length is unknown. */
    964       break;
    965 
    966     case TT_MP4_RAW:
    967       if ((INT)FDKgetValidBits(hBs) <= 0 && layer == 0) {
    968         err = TRANSPORTDEC_NOT_ENOUGH_BITS;
    969       }
    970       /* One Access Unit was filled into buffer.
    971          So get the length out of the buffer. */
    972       hTp->auLength[layer] = FDKgetValidBits(hBs);
    973       hTp->flags |= TPDEC_SYNCOK;
    974       break;
    975 
    976     case TT_RSVD50:
    977     case TT_MP4_ADTS:
    978     case TT_MP4_LOAS:
    979     case TT_MP4_LATM_MCP0:
    980     case TT_MP4_LATM_MCP1:
    981       err = transportDec_readStream(hTp, layer);
    982       break;
    983 
    984     default:
    985       err = TRANSPORTDEC_UNSUPPORTED_FORMAT;
    986       break;
    987   }
    988 
    989   if (err == TRANSPORTDEC_OK) {
    990     hTp->accessUnitAnchor[layer] = FDKgetValidBits(hBs);
    991   } else {
    992     hTp->accessUnitAnchor[layer] = 0;
    993   }
    994 
    995 bail:
    996   return err;
    997 }
    998 
    999 INT transportDec_GetAuBitsRemaining( const HANDLE_TRANSPORTDEC hTp, const UINT layer )
   1000 {
   1001   INT bits;
   1002 
   1003   if (hTp->accessUnitAnchor[layer] > 0 && hTp->auLength[layer] > 0) {
   1004     bits = hTp->auLength[layer] - (hTp->accessUnitAnchor[layer] - FDKgetValidBits(&hTp->bitStream[layer]));
   1005   } else {
   1006     bits = FDKgetValidBits(&hTp->bitStream[layer]);
   1007   }
   1008 
   1009   return bits;
   1010 }
   1011 
   1012 INT transportDec_GetAuBitsTotal( const HANDLE_TRANSPORTDEC hTp, const UINT layer )
   1013 {
   1014   return hTp->auLength[layer];
   1015 }
   1016 
   1017 TRANSPORTDEC_ERROR transportDec_GetMissingAccessUnitCount ( INT *pNAccessUnits, HANDLE_TRANSPORTDEC hTp )
   1018 {
   1019   *pNAccessUnits = hTp->missingAccessUnits;
   1020 
   1021   return TRANSPORTDEC_OK;
   1022 }
   1023 
   1024 /* Inform the transportDec layer that reading of access unit has finished. */
   1025 TRANSPORTDEC_ERROR transportDec_EndAccessUnit(HANDLE_TRANSPORTDEC hTp)
   1026 {
   1027   TRANSPORTDEC_ERROR err = TRANSPORTDEC_OK;
   1028 
   1029   err = transportDec_AdjustEndOfAccessUnit(hTp);
   1030 
   1031   switch (hTp->transportFmt) {
   1032     case TT_MP4_LOAS:
   1033     case TT_MP4_LATM_MCP0:
   1034     case TT_MP4_LATM_MCP1:
   1035       break;
   1036     default:
   1037       break;
   1038   }
   1039 
   1040   return err;
   1041 }
   1042 
   1043 TRANSPORTDEC_ERROR transportDec_SetParam ( const HANDLE_TRANSPORTDEC hTp,
   1044                                            const TPDEC_PARAM        param,
   1045                                            const INT                value)
   1046 {
   1047   TRANSPORTDEC_ERROR error = TRANSPORTDEC_OK;
   1048 
   1049   switch (param) {
   1050     case TPDEC_PARAM_MINIMIZE_DELAY:
   1051       if (value) {
   1052         hTp->flags |= TPDEC_MINIMIZE_DELAY;
   1053       } else {
   1054         hTp->flags &= ~TPDEC_MINIMIZE_DELAY;
   1055       }
   1056       break;
   1057     case TPDEC_PARAM_EARLY_CONFIG:
   1058       if (value) {
   1059         hTp->flags |= TPDEC_EARLY_CONFIG;
   1060       } else {
   1061         hTp->flags &= ~TPDEC_EARLY_CONFIG;
   1062       }
   1063       break;
   1064     case TPDEC_PARAM_IGNORE_BUFFERFULLNESS:
   1065       if (value) {
   1066         hTp->flags |= TPDEC_IGNORE_BUFFERFULLNESS;
   1067       } else {
   1068         hTp->flags &= ~TPDEC_IGNORE_BUFFERFULLNESS;
   1069       }
   1070       break;
   1071     case TPDEC_PARAM_SET_BITRATE:
   1072       hTp->avgBitRate = value;
   1073       break;
   1074     case TPDEC_PARAM_BURST_PERIOD:
   1075       hTp->burstPeriod = value;
   1076       break;
   1077     case TPDEC_PARAM_RESET:
   1078       {
   1079         int i;
   1080 
   1081         for (i=0; i<(1*2); i++) {
   1082           FDKresetBitbuffer(&hTp->bitStream[i]);
   1083           hTp->auLength[i] = 0;
   1084           hTp->accessUnitAnchor[i] = 0;
   1085         }
   1086         hTp->flags &= ~(TPDEC_SYNCOK|TPDEC_LOST_FRAMES_PENDING);
   1087         hTp->remainder = 0;
   1088         hTp->avgBitRate = 0;
   1089         hTp->missingAccessUnits = 0;
   1090         hTp->numberOfRawDataBlocks = 0;
   1091         hTp->globalFramePos = 0;
   1092         hTp->holdOffFrames = 0;
   1093       }
   1094       break;
   1095   }
   1096 
   1097   return error;
   1098 }
   1099 
   1100 UINT transportDec_GetNrOfSubFrames(HANDLE_TRANSPORTDEC hTp)
   1101 {
   1102   UINT nSubFrames = 0;
   1103 
   1104   if (hTp == NULL)
   1105     return 0;
   1106 
   1107   if (hTp->transportFmt==TT_MP4_LATM_MCP1 || hTp->transportFmt==TT_MP4_LATM_MCP0 || hTp->transportFmt==TT_MP4_LOAS)
   1108     nSubFrames = CLatmDemux_GetNrOfSubFrames(&hTp->parser.latm);
   1109   else if (hTp->transportFmt==TT_MP4_ADTS)
   1110     nSubFrames = hTp->parser.adts.bs.num_raw_blocks;
   1111 
   1112   return nSubFrames;
   1113 }
   1114 
   1115 void transportDec_Close(HANDLE_TRANSPORTDEC *phTp)
   1116 {
   1117   if (phTp != NULL)
   1118   {
   1119     if (*phTp != NULL) {
   1120       if ((*phTp)->transportFmt != TT_MP4_RAW && (*phTp)->transportFmt != TT_DRM) {
   1121         FreeRam_TransportDecoderBuffer(&(*phTp)->bsBuffer);
   1122       }
   1123       if (*phTp != NULL) {
   1124         FreeRam_TransportDecoder(phTp);
   1125       }
   1126     }
   1127   }
   1128 }
   1129 
   1130 TRANSPORTDEC_ERROR transportDec_GetLibInfo( LIB_INFO *info )
   1131 {
   1132   int i;
   1133 
   1134   if (info == NULL) {
   1135     return TRANSPORTDEC_UNKOWN_ERROR;
   1136   }
   1137 
   1138   /* search for next free tab */
   1139   for (i = 0; i < FDK_MODULE_LAST; i++) {
   1140     if (info[i].module_id == FDK_NONE) break;
   1141   }
   1142   if (i == FDK_MODULE_LAST) return TRANSPORTDEC_UNKOWN_ERROR;
   1143   info += i;
   1144 
   1145   info->module_id  = FDK_TPDEC;
   1146   info->build_date = __DATE__;
   1147   info->build_time = __TIME__;
   1148   info->title      = TP_LIB_TITLE;
   1149   info->version    = LIB_VERSION(TP_LIB_VL0, TP_LIB_VL1, TP_LIB_VL2);
   1150   LIB_VERSION_STRING(info);
   1151   info->flags = 0
   1152     | CAPF_ADIF
   1153     | CAPF_ADTS
   1154     | CAPF_LATM
   1155     | CAPF_LOAS
   1156     | CAPF_RAWPACKETS
   1157     ;
   1158 
   1159   return TRANSPORTDEC_OK; /* FDKERR_NOERROR; */
   1160 }
   1161 
   1162 
   1163 int  transportDec_CrcStartReg(HANDLE_TRANSPORTDEC pTp, INT mBits)
   1164 {
   1165   switch (pTp->transportFmt) {
   1166   case TT_MP4_ADTS:
   1167     return adtsRead_CrcStartReg(&pTp->parser.adts, &pTp->bitStream[0], mBits);
   1168   default:
   1169     return 0;
   1170   }
   1171 }
   1172 
   1173 void transportDec_CrcEndReg(HANDLE_TRANSPORTDEC pTp, INT reg)
   1174 {
   1175   switch (pTp->transportFmt) {
   1176   case TT_MP4_ADTS:
   1177     adtsRead_CrcEndReg(&pTp->parser.adts, &pTp->bitStream[0], reg);
   1178     break;
   1179   default:
   1180     break;
   1181   }
   1182 }
   1183 
   1184 TRANSPORTDEC_ERROR transportDec_CrcCheck(HANDLE_TRANSPORTDEC pTp)
   1185 {
   1186   switch (pTp->transportFmt) {
   1187   case TT_MP4_ADTS:
   1188     if ( (pTp->parser.adts.bs.num_raw_blocks > 0) && (pTp->parser.adts.bs.protection_absent == 0) )
   1189     {
   1190       HANDLE_FDK_BITSTREAM hBs = &pTp->bitStream[0];
   1191       int bitDiff;
   1192 
   1193       /* Calculate possible offset to CRC value. */
   1194       bitDiff  = pTp->parser.adts.rawDataBlockDist[pTp->parser.adts.bs.num_raw_blocks-pTp->numberOfRawDataBlocks]<<3;
   1195       bitDiff -= pTp->globalFramePos - FDKgetValidBits(hBs) + 16;
   1196       FDKpushBiDirectional(hBs, bitDiff);
   1197       pTp->parser.adts.crcReadValue = FDKreadBits(hBs, 16);
   1198     }
   1199     return adtsRead_CrcCheck(&pTp->parser.adts);
   1200   default:
   1201     return TRANSPORTDEC_OK;
   1202   }
   1203 }
   1204