/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android

© Copyright  1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.

 1.    INTRODUCTION
The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software
that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding
scheme for digital audio. This FDK AAC Codec software is intended to be used on
a wide variety of Android devices.

AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient
general perceptual audio codecs. AAC-ELD is considered the best-performing
full-bandwidth communications codec by independent studies and is widely
deployed. AAC has been standardized by ISO and IEC as part of the MPEG
specifications.

Patent licenses for necessary patent claims for the FDK AAC Codec (including
those of Fraunhofer) may be obtained through Via Licensing
(www.vialicensing.com) or through the respective patent owners individually for
the purpose of encoding or decoding bit streams in products that are compliant
with the ISO/IEC MPEG audio standards. Please note that most manufacturers of
Android devices already license these patent claims through Via Licensing or
directly from the patent owners, and therefore FDK AAC Codec software may
already be covered under those patent licenses when it is used for those
licensed purposes only.

Commercially-licensed AAC software libraries, including floating-point versions
with enhanced sound quality, are also available from Fraunhofer. Users are
encouraged to check the Fraunhofer website for additional applications
information and documentation.

2.    COPYRIGHT LICENSE

Redistribution and use in source and binary forms, with or without modification,
are permitted without payment of copyright license fees provided that you
satisfy the following conditions:

You must retain the complete text of this software license in redistributions of
the FDK AAC Codec or your modifications thereto in source code form.

You must retain the complete text of this software license in the documentation
and/or other materials provided with redistributions of the FDK AAC Codec or
your modifications thereto in binary form. You must make available free of
charge copies of the complete source code of the FDK AAC Codec and your
modifications thereto to recipients of copies in binary form.

The name of Fraunhofer may not be used to endorse or promote products derived
from this library without prior written permission.

You may not charge copyright license fees for anyone to use, copy or distribute
the FDK AAC Codec software or your modifications thereto.

Your modified versions of the FDK AAC Codec must carry prominent notices stating
that you changed the software and the date of any change. For modified versions
of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android"
must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK
AAC Codec Library for Android."

3.    NO PATENT LICENSE

NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without
limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE.
Fraunhofer provides no warranty of patent non-infringement with respect to this
software.

You may use this FDK AAC Codec software or modifications thereto only for
purposes that are authorized by appropriate patent licenses.

4.    DISCLAIMER

This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright
holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
including but not limited to the implied warranties of merchantability and
fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary,
or consequential damages, including but not limited to procurement of substitute
goods or services; loss of use, data, or profits, or business interruption,
however caused and on any theory of liability, whether in contract, strict
liability, or tort (including negligence), arising in any way out of the use of
this software, even if advised of the possibility of such damage.

5.    CONTACT INFORMATION

Fraunhofer Institute for Integrated Circuits IIS
Attention: Audio and Multimedia Departments - FDK AAC LL
Am Wolfsmantel 33
91058 Erlangen, Germany

www.iis.fraunhofer.de/amm
amm-info@iis.fraunhofer.de
----------------------------------------------------------------------------- */

/******************* MPEG transport format decoder library *********************

   Author(s):   Daniel Homm

   Description:

*******************************************************************************/

#include "tpdec_latm.h"

#include "FDK_bitstream.h"

#define TPDEC_TRACKINDEX(p, l) (1 * (p) + (l))

static UINT CLatmDemux_GetValue(HANDLE_FDK_BITSTREAM bs) {
  UCHAR bytesForValue = 0, tmp = 0;
  int value = 0;

  bytesForValue = (UCHAR)FDKreadBits(bs, 2);

  for (UINT i = 0; i <= bytesForValue; i++) {
    value <<= 8;
    tmp = (UCHAR)FDKreadBits(bs, 8);
    value += tmp;
  }

  return value;
}

static TRANSPORTDEC_ERROR CLatmDemux_ReadAudioMuxElement(
    HANDLE_FDK_BITSTREAM bs, CLatmDemux *pLatmDemux, int m_muxConfigPresent,
    CSTpCallBacks *pTpDecCallbacks, CSAudioSpecificConfig *pAsc,
    int *pfConfigFound) {
  TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK;

  if (m_muxConfigPresent) {
    pLatmDemux->m_useSameStreamMux = FDKreadBits(bs, 1);

    if (!pLatmDemux->m_useSameStreamMux) {
      int i;
      UCHAR configChanged = 0;
      UCHAR configMode = 0;

      FDK_BITSTREAM bsAnchor;

      FDK_BITSTREAM bsAnchorDummyParse;

      if (!pLatmDemux->applyAsc) {
        bsAnchorDummyParse = *bs;
        pLatmDemux->newCfgHasAudioPreRoll = 0;
        /* do dummy-parsing of ASC to determine if there is an audioPreRoll */
        configMode |= AC_CM_DET_CFG_CHANGE;
        if (TRANSPORTDEC_OK !=
            (ErrorStatus = CLatmDemux_ReadStreamMuxConfig(
                 bs, pLatmDemux, pTpDecCallbacks, pAsc, pfConfigFound,
                 configMode, configChanged))) {
          goto bail;
        }

        /* Allow flushing only when audioPreroll functionality is enabled in
         * current and new config otherwise the new config can be applied
         * immediately. */
        if (pAsc->m_sc.m_usacConfig.element[0]
                .extElement.usacExtElementHasAudioPreRoll &&
            pLatmDemux->newCfgHasAudioPreRoll) {
          pLatmDemux->newCfgHasAudioPreRoll = 0;
          /* with audioPreRoll we must flush before applying new cfg */
          pLatmDemux->applyAsc = 0;
        } else {
          *bs = bsAnchorDummyParse;
          pLatmDemux->applyAsc = 1; /* apply new config immediate */
        }
      }

      if (pLatmDemux->applyAsc) {
        for (i = 0; i < 2; i++) {
          configMode = 0;

          if (i == 0) {
            configMode |= AC_CM_DET_CFG_CHANGE;
            bsAnchor = *bs;
          } else {
            configMode |= AC_CM_ALLOC_MEM;
            *bs = bsAnchor;
          }

          if (TRANSPORTDEC_OK !=
              (ErrorStatus = CLatmDemux_ReadStreamMuxConfig(
                   bs, pLatmDemux, pTpDecCallbacks, pAsc, pfConfigFound,
                   configMode, configChanged))) {
            goto bail;
          }

          if (ErrorStatus == TRANSPORTDEC_OK) {
            if ((i == 0) && (pAsc->AacConfigChanged || pAsc->SbrConfigChanged ||
                             pAsc->SacConfigChanged)) {
              int errC;

              configChanged = 1;
              errC = pTpDecCallbacks->cbFreeMem(pTpDecCallbacks->cbFreeMemData,
                                                pAsc);
              if (errC != 0) {
                ErrorStatus = TRANSPORTDEC_PARSE_ERROR;
                goto bail;
              }
            }
          }
        }
      }
    }
  }

  /* If there was no configuration read, its not possible to parse
   * PayloadLengthInfo below. */
  if (!*pfConfigFound) {
    ErrorStatus = TRANSPORTDEC_SYNC_ERROR;
    goto bail;
  }

  if (pLatmDemux->m_AudioMuxVersionA == 0) {
    /* Do only once per call, because parsing and decoding is done in-line. */
    if (TRANSPORTDEC_OK !=
        (ErrorStatus = CLatmDemux_ReadPayloadLengthInfo(bs, pLatmDemux))) {
      *pfConfigFound = 0;
      goto bail;
    }
  } else {
    /* audioMuxVersionA > 0 is reserved for future extensions */
    ErrorStatus = TRANSPORTDEC_UNSUPPORTED_FORMAT;
    *pfConfigFound = 0;
    goto bail;
  }

bail:
  if (ErrorStatus != TRANSPORTDEC_OK) {
    pLatmDemux->applyAsc = 1;
  }

  return (ErrorStatus);
}

TRANSPORTDEC_ERROR CLatmDemux_Read(HANDLE_FDK_BITSTREAM bs,
                                   CLatmDemux *pLatmDemux, TRANSPORT_TYPE tt,
                                   CSTpCallBacks *pTpDecCallbacks,
                                   CSAudioSpecificConfig *pAsc,
                                   int *pfConfigFound,
                                   const INT ignoreBufferFullness) {
  UINT cntBits;
  UINT cmpBufferFullness;
  UINT audioMuxLengthBytesLast = 0;
  TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK;

  cntBits = FDKgetValidBits(bs);

  if ((INT)cntBits < MIN_LATM_HEADERLENGTH) {
    return TRANSPORTDEC_NOT_ENOUGH_BITS;
  }

  if (TRANSPORTDEC_OK != (ErrorStatus = CLatmDemux_ReadAudioMuxElement(
                              bs, pLatmDemux, (tt != TT_MP4_LATM_MCP0),
                              pTpDecCallbacks, pAsc, pfConfigFound)))
    return (ErrorStatus);

  if (!ignoreBufferFullness) {
    cmpBufferFullness =
        24 + audioMuxLengthBytesLast * 8 +
        pLatmDemux->m_linfo[0][0].m_bufferFullness *
            pAsc[TPDEC_TRACKINDEX(0, 0)].m_channelConfiguration * 32;

    /* evaluate buffer fullness */

    if (pLatmDemux->m_linfo[0][0].m_bufferFullness != 0xFF) {
      if (!pLatmDemux->BufferFullnessAchieved) {
        if (cntBits < cmpBufferFullness) {
          /* condition for start of decoding is not fulfilled */

          /* the current frame will not be decoded */
          return TRANSPORTDEC_NOT_ENOUGH_BITS;
        } else {
          pLatmDemux->BufferFullnessAchieved = 1;
        }
      }
    }
  }

  return (ErrorStatus);
}

TRANSPORTDEC_ERROR CLatmDemux_ReadStreamMuxConfig(
    HANDLE_FDK_BITSTREAM bs, CLatmDemux *pLatmDemux,
    CSTpCallBacks *pTpDecCallbacks, CSAudioSpecificConfig *pAsc,
    int *pfConfigFound, UCHAR configMode, UCHAR configChanged) {
  CSAudioSpecificConfig ascDummy; /* the actual config is needed for flushing,
                                     after that new config can be parsed */
  CSAudioSpecificConfig *pAscDummy;
  pAscDummy = &ascDummy;
  pLatmDemux->usacExplicitCfgChanged = 0;
  LATM_LAYER_INFO *p_linfo = NULL;
  TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK;
  UCHAR updateConfig[1 * 1] = {0};

  pLatmDemux->m_AudioMuxVersion = FDKreadBits(bs, 1);

  if (pLatmDemux->m_AudioMuxVersion == 0) {
    pLatmDemux->m_AudioMuxVersionA = 0;
  } else {
    pLatmDemux->m_AudioMuxVersionA = FDKreadBits(bs, 1);
  }

  if (pLatmDemux->m_AudioMuxVersionA == 0) {
    if (pLatmDemux->m_AudioMuxVersion == 1) {
      pLatmDemux->m_taraBufferFullness = CLatmDemux_GetValue(bs);
    }
    pLatmDemux->m_allStreamsSameTimeFraming = FDKreadBits(bs, 1);
    pLatmDemux->m_noSubFrames = FDKreadBits(bs, 6) + 1;
    pLatmDemux->m_numProgram = FDKreadBits(bs, 4) + 1;

    if (pLatmDemux->m_numProgram > LATM_MAX_PROG) {
      ErrorStatus = TRANSPORTDEC_UNSUPPORTED_FORMAT;
      goto bail;
    }

    int idCnt = 0;
    for (UINT prog = 0; prog < pLatmDemux->m_numProgram; prog++) {
      pLatmDemux->m_numLayer[prog] = FDKreadBits(bs, 3) + 1;
      if (pLatmDemux->m_numLayer[prog] > LATM_MAX_LAYER) {
        ErrorStatus = TRANSPORTDEC_UNSUPPORTED_FORMAT;
        goto bail;
      }

      for (UINT lay = 0; lay < pLatmDemux->m_numLayer[prog]; lay++) {
        int useSameConfig;
        p_linfo = &pLatmDemux->m_linfo[prog][lay];

        p_linfo->m_streamID = idCnt++;
        p_linfo->m_frameLengthInBits = 0;

        if ((prog == 0) && (lay == 0)) {
          useSameConfig = 0;
        } else {
          useSameConfig = FDKreadBits(bs, 1);
        }

        if (useSameConfig) {
          if (lay > 0) {
            FDKmemcpy(&pAsc[TPDEC_TRACKINDEX(prog, lay)],
                      &pAsc[TPDEC_TRACKINDEX(prog, lay - 1)],
                      sizeof(CSAudioSpecificConfig));
          } else {
            ErrorStatus = TRANSPORTDEC_PARSE_ERROR;
            goto bail;
          }
        } else {
          UINT usacConfigLengthPrev = 0;
          UCHAR usacConfigPrev[TP_USAC_MAX_CONFIG_LEN];

          if (!(pLatmDemux->applyAsc) &&
              (pAsc[TPDEC_TRACKINDEX(prog, lay)].m_aot == AOT_USAC)) {
            usacConfigLengthPrev =
                (UINT)(pAsc[TPDEC_TRACKINDEX(prog, lay)]
                           .m_sc.m_usacConfig.UsacConfigBits +
                       7) >>
                3; /* store previous USAC config length */
            if (usacConfigLengthPrev > TP_USAC_MAX_CONFIG_LEN) {
              ErrorStatus = TRANSPORTDEC_PARSE_ERROR;
              goto bail;
            }
            FDKmemclear(usacConfigPrev, TP_USAC_MAX_CONFIG_LEN);
            FDKmemcpy(
                usacConfigPrev,
                &pAsc[TPDEC_TRACKINDEX(prog, lay)].m_sc.m_usacConfig.UsacConfig,
                usacConfigLengthPrev); /* store previous USAC config */
          }
          if (pLatmDemux->m_AudioMuxVersion == 1) {
            FDK_BITSTREAM tmpBs;
            UINT ascLen = 0;
            ascLen = CLatmDemux_GetValue(bs);
            /* The ascLen could be wrong, so check if validBits<=bufBits*/
            if (ascLen > FDKgetValidBits(bs)) {
              ErrorStatus = TRANSPORTDEC_PARSE_ERROR;
              goto bail;
            }
            FDKsyncCache(bs);
            tmpBs = *bs;
            tmpBs.hBitBuf.ValidBits = ascLen;

            /* Read ASC */
            if (pLatmDemux->applyAsc) {
              if (TRANSPORTDEC_OK !=
                  (ErrorStatus = AudioSpecificConfig_Parse(
                       &pAsc[TPDEC_TRACKINDEX(prog, lay)], &tmpBs, 1,
                       pTpDecCallbacks, configMode, configChanged,
                       AOT_NULL_OBJECT)))
                goto bail;
            } else {
              if (TRANSPORTDEC_OK !=
                  (ErrorStatus = AudioSpecificConfig_Parse(
                       pAscDummy, &tmpBs, 1, pTpDecCallbacks, configMode,
                       configChanged, AOT_NULL_OBJECT)))
                goto bail;
            }

            /* The field p_linfo->m_ascLen could be wrong, so check if */
            if (0 > (INT)FDKgetValidBits(&tmpBs)) {
              ErrorStatus = TRANSPORTDEC_PARSE_ERROR;
              goto bail;
            }
            FDKpushFor(bs, ascLen); /* position bitstream after ASC */
          } else {
            /* Read ASC */
            if (pLatmDemux->applyAsc) {
              if (TRANSPORTDEC_OK != (ErrorStatus = AudioSpecificConfig_Parse(
                                          &pAsc[TPDEC_TRACKINDEX(prog, lay)],
                                          bs, 0, pTpDecCallbacks, configMode,
                                          configChanged, AOT_NULL_OBJECT)))
                goto bail;
            } else {
              if (TRANSPORTDEC_OK !=
                  (ErrorStatus = AudioSpecificConfig_Parse(
                       pAscDummy, bs, 0, pTpDecCallbacks, configMode,
                       configChanged, AOT_NULL_OBJECT)))
                goto bail;
            }
          }
          if (!pLatmDemux->applyAsc) {
            updateConfig[TPDEC_TRACKINDEX(prog, lay)] = 0;
          } else {
            updateConfig[TPDEC_TRACKINDEX(prog, lay)] = 1;
          }

          if (!pLatmDemux->applyAsc) {
            if (pAscDummy[TPDEC_TRACKINDEX(prog, lay)].m_aot ==
                AOT_USAC) { /* flush in case SMC has changed */
              const UINT usacConfigLength =
                  (UINT)(pAscDummy->m_sc.m_usacConfig.UsacConfigBits + 7) >> 3;
              if (usacConfigLength > TP_USAC_MAX_CONFIG_LEN) {
                ErrorStatus = TRANSPORTDEC_PARSE_ERROR;
                goto bail;
              }
              if (usacConfigLength != usacConfigLengthPrev) {
                FDKmemclear(&pAsc[TPDEC_TRACKINDEX(prog, lay)]
                                 .m_sc.m_usacConfig.UsacConfig,
                            TP_USAC_MAX_CONFIG_LEN);
                FDKmemcpy(&pAsc[TPDEC_TRACKINDEX(prog, lay)]
                               .m_sc.m_usacConfig.UsacConfig,
                          &pAscDummy->m_sc.m_usacConfig.UsacConfig,
                          usacConfigLength); /* store new USAC config */
                pAsc[TPDEC_TRACKINDEX(prog, lay)]
                    .m_sc.m_usacConfig.UsacConfigBits =
                    pAscDummy->m_sc.m_usacConfig.UsacConfigBits;
                pLatmDemux->usacExplicitCfgChanged = 1;
              } else {
                if (FDKmemcmp(usacConfigPrev,
                              pAscDummy->m_sc.m_usacConfig.UsacConfig,
                              usacConfigLengthPrev)) {
                  FDKmemclear(&pAsc[TPDEC_TRACKINDEX(prog, lay)]
                                   .m_sc.m_usacConfig.UsacConfig,
                              TP_USAC_MAX_CONFIG_LEN);
                  FDKmemcpy(&pAsc[TPDEC_TRACKINDEX(prog, lay)]
                                 .m_sc.m_usacConfig.UsacConfig,
                            &pAscDummy->m_sc.m_usacConfig.UsacConfig,
                            usacConfigLength); /* store new USAC config */
                  pAsc[TPDEC_TRACKINDEX(prog, lay)]
                      .m_sc.m_usacConfig.UsacConfigBits =
                      pAscDummy->m_sc.m_usacConfig.UsacConfigBits;
                  pLatmDemux->usacExplicitCfgChanged = 1;
                }
              }

              if (pAscDummy[TPDEC_TRACKINDEX(prog, lay)]
                      .m_sc.m_usacConfig.m_usacNumElements) {
                if (pAscDummy[TPDEC_TRACKINDEX(prog, lay)]
                        .m_sc.m_usacConfig.element[0]
                        .extElement.usacExtElementHasAudioPreRoll) {
                  pLatmDemux->newCfgHasAudioPreRoll =
                      1; /* if dummy parsed cfg has audioPreRoll we first flush
                            before applying new cfg */
                }
              }
            }
          }
        }

        p_linfo->m_frameLengthType = FDKreadBits(bs, 3);
        switch (p_linfo->m_frameLengthType) {
          case 0:
            p_linfo->m_bufferFullness = FDKreadBits(bs, 8);

            if (!pLatmDemux->m_allStreamsSameTimeFraming) {
              if ((lay > 0) &&
                  (pAsc[TPDEC_TRACKINDEX(prog, lay)].m_aot == AOT_AAC_SCAL ||
                   pAsc[TPDEC_TRACKINDEX(prog, lay)].m_aot ==
                       AOT_ER_AAC_SCAL) &&
                  (pAsc[TPDEC_TRACKINDEX(prog, lay - 1)].m_aot == AOT_CELP ||
                   pAsc[TPDEC_TRACKINDEX(prog, lay - 1)].m_aot ==
                       AOT_ER_CELP)) { /* The layer maybe
                                          ignored later so
                                          read it anyway: */
                /* coreFrameOffset = */ FDKreadBits(bs, 6);
              }
            }
            break;
          case 1:
            p_linfo->m_frameLengthInBits = FDKreadBits(bs, 9);
            break;
          case 3:
          case 4:
          case 5:
            /* CELP */
          case 6:
          case 7:
            /* HVXC */
          default:
            ErrorStatus = TRANSPORTDEC_PARSE_ERROR;
            goto bail;
        } /* switch framelengthtype*/

      } /* layer loop */
    }   /* prog loop */

    pLatmDemux->m_otherDataPresent = FDKreadBits(bs, 1);
    pLatmDemux->m_otherDataLength = 0;

    if (pLatmDemux->m_otherDataPresent) {
      if (pLatmDemux->m_AudioMuxVersion == 1) {
        pLatmDemux->m_otherDataLength = CLatmDemux_GetValue(bs);
      } else {
        int otherDataLenEsc = 0;
        do {
          pLatmDemux->m_otherDataLength <<= 8;  // *= 256
          otherDataLenEsc = FDKreadBits(bs, 1);
          pLatmDemux->m_otherDataLength += FDKreadBits(bs, 8);
        } while (otherDataLenEsc);
      }
      if (pLatmDemux->m_audioMuxLengthBytes <
          (pLatmDemux->m_otherDataLength >> 3)) {
        ErrorStatus = TRANSPORTDEC_PARSE_ERROR;
        goto bail;
      }
    }

    pLatmDemux->m_crcCheckPresent = FDKreadBits(bs, 1);

    if (pLatmDemux->m_crcCheckPresent) {
      FDKreadBits(bs, 8);
    }

  } else {
    /* audioMuxVersionA > 0 is reserved for future extensions */
    ErrorStatus = TRANSPORTDEC_UNSUPPORTED_FORMAT;
  }

  /* Configure source decoder: */
  if (ErrorStatus == TRANSPORTDEC_OK) {
    UINT prog;
    for (prog = 0; prog < pLatmDemux->m_numProgram; prog++) {
      UINT lay;
      for (lay = 0; lay < pLatmDemux->m_numLayer[prog]; lay++) {
        if (updateConfig[TPDEC_TRACKINDEX(prog, lay)] != 0) {
          int cbError;
          cbError = pTpDecCallbacks->cbUpdateConfig(
              pTpDecCallbacks->cbUpdateConfigData,
              &pAsc[TPDEC_TRACKINDEX(prog, lay)],
              pAsc[TPDEC_TRACKINDEX(prog, lay)].configMode,
              &pAsc[TPDEC_TRACKINDEX(prog, lay)].AacConfigChanged);
          if (cbError == TRANSPORTDEC_NEED_TO_RESTART) {
            *pfConfigFound = 0;
            ErrorStatus = TRANSPORTDEC_NEED_TO_RESTART;
            goto bail;
          }
          if (cbError != 0) {
            *pfConfigFound = 0;
            if (lay == 0) {
              ErrorStatus = TRANSPORTDEC_SYNC_ERROR;
              goto bail;
            }
          } else {
            *pfConfigFound = 1;
          }
        } else {
          *pfConfigFound = 1;
        }
      }
    }
  }

bail:
  if (ErrorStatus != TRANSPORTDEC_OK) {
    UCHAR applyAsc = pLatmDemux->applyAsc;
    FDKmemclear(pLatmDemux, sizeof(CLatmDemux)); /* reset structure */
    pLatmDemux->applyAsc = applyAsc;
  } else {
    /* no error and config parsing is finished */
    if (configMode == AC_CM_ALLOC_MEM) pLatmDemux->applyAsc = 0;
  }

  return (ErrorStatus);
}

TRANSPORTDEC_ERROR CLatmDemux_ReadPayloadLengthInfo(HANDLE_FDK_BITSTREAM bs,
                                                    CLatmDemux *pLatmDemux) {
  TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK;
  int totalPayloadBits = 0;

  if (pLatmDemux->m_allStreamsSameTimeFraming == 1) {
    FDK_ASSERT(pLatmDemux->m_numProgram <= LATM_MAX_PROG);
    for (UINT prog = 0; prog < pLatmDemux->m_numProgram; prog++) {
      FDK_ASSERT(pLatmDemux->m_numLayer[prog] <= LATM_MAX_LAYER);
      for (UINT lay = 0; lay < pLatmDemux->m_numLayer[prog]; lay++) {
        LATM_LAYER_INFO *p_linfo = &pLatmDemux->m_linfo[prog][lay];

        switch (p_linfo->m_frameLengthType) {
          case 0:
            p_linfo->m_frameLengthInBits = CLatmDemux_ReadAuChunkLengthInfo(bs);
            totalPayloadBits += p_linfo->m_frameLengthInBits;
            break;
          case 3:
          case 5:
          case 7:
          default:
            return TRANSPORTDEC_PARSE_ERROR;  // AAC_DEC_LATM_INVALIDFRAMELENGTHTYPE;
        }
      }
    }
  } else {
    ErrorStatus = TRANSPORTDEC_PARSE_ERROR;  // AAC_DEC_LATM_TIMEFRAMING;
  }
  if (pLatmDemux->m_audioMuxLengthBytes > (UINT)0 &&
      totalPayloadBits > (int)pLatmDemux->m_audioMuxLengthBytes * 8) {
    return TRANSPORTDEC_PARSE_ERROR;
  }

  return (ErrorStatus);
}

int CLatmDemux_ReadAuChunkLengthInfo(HANDLE_FDK_BITSTREAM bs) {
  UCHAR endFlag;
  int len = 0;

  do {
    UCHAR tmp = (UCHAR)FDKreadBits(bs, 8);
    endFlag = (tmp < 255);

    len += tmp;

  } while (endFlag == 0);

  len <<= 3; /* convert from bytes to bits */

  return len;
}

UINT CLatmDemux_GetFrameLengthInBits(CLatmDemux *pLatmDemux, const UINT prog,
                                     const UINT layer) {
  UINT nFrameLenBits = 0;
  if (prog < pLatmDemux->m_numProgram) {
    if (layer < pLatmDemux->m_numLayer[prog]) {
      nFrameLenBits = pLatmDemux->m_linfo[prog][layer].m_frameLengthInBits;
    }
  }
  return nFrameLenBits;
}

UINT CLatmDemux_GetOtherDataPresentFlag(CLatmDemux *pLatmDemux) {
  return pLatmDemux->m_otherDataPresent ? 1 : 0;
}

UINT CLatmDemux_GetOtherDataLength(CLatmDemux *pLatmDemux) {
  return pLatmDemux->m_otherDataLength;
}

UINT CLatmDemux_GetNrOfSubFrames(CLatmDemux *pLatmDemux) {
  return pLatmDemux->m_noSubFrames;
}

UINT CLatmDemux_GetNrOfLayers(CLatmDemux *pLatmDemux, const UINT prog) {
  UINT numLayer = 0;
  if (prog < pLatmDemux->m_numProgram) {
    numLayer = pLatmDemux->m_numLayer[prog];
  }
  return numLayer;
}
