videoeditorengine/mp3aacManipLib/MP3Gain/src/mpif.cpp
changeset 0 951a5db380a0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/videoeditorengine/mp3aacManipLib/MP3Gain/src/mpif.cpp	Fri Jan 29 14:08:33 2010 +0200
@@ -0,0 +1,909 @@
+/*
+* Copyright (c) 2010 Ixonos Plc.
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - Initial contribution
+*
+* Contributors:
+* Ixonos Plc
+*
+* Description:
+*
+*/
+
+
+/**************************************************************************
+  mpif.cpp - MPEG-1, MPEG-2 LSF and MPEG-2.5 file format implementations.
+
+  Author(s): Juha Ojanpera
+  Copyright (c) 1999-2004 by Nokia Research Center, Speech and Audio Systems.
+  *************************************************************************/
+
+/*-- project headers --*/
+#include "mpif.h"
+//#include "auddef.h"
+#include "mpheader.h"
+#include "nok_bits.h"
+#include "mstream.h"
+
+
+/**************************************************************************
+  Internal Objects
+  *************************************************************************/
+
+/*
+   Purpose:     Sync lost after 16384 bytes.
+   Explanation: - */
+#define SYNC_THRESHOLD (16384 << 3)
+
+/**************************************************************************
+  Title        : main_data_slots
+
+  Purpose      : Computes the number of bytes for the layer III payload. The
+                 payload consists of the scalefactors and quantized data of
+                 the channel(s).
+
+  Usage        : y = main_data_slots(mp)
+
+  Input        : mp - mp3 file format parameters
+
+  Output       : y  - # of payload bytes for this frame
+
+  Author(s)    : Juha Ojanpera
+  *************************************************************************/
+
+INLINE int32
+main_data_slots(TMpTransportHandle *tHandle)
+{
+  int16 nSlots;
+
+  if(bit_rate(&tHandle->header))
+  {
+    nSlots = tHandle->SlotTable[bit_rate_idx(&tHandle->header)];
+
+    if(padding(&tHandle->header))
+      nSlots++;
+    if(error_protection(&tHandle->header))
+      nSlots -= 2;
+  }
+  else
+  {
+    nSlots = tHandle->FreeFormatSlots;
+
+    if(padding(&tHandle->header))
+      nSlots++;
+  }
+
+  return(nSlots);
+}
+
+/*
+ * Maximum # of bits needed for the header. Note that only
+ * 20 bits are read since 12 bits were read already when 
+ * locating the start of frame. 16 bits are needed for
+ * the optional CRC codeword.
+ */
+#define MAX_MP_HEADER_SIZE (20 + 16)
+
+/**************************************************************************
+  Title        : decode_header
+
+  Purpose      : Reads header information (excluding syncword) from the bitstream.
+
+  Usage        : decode_header(tHandle, bs)
+
+  Input        : tHandle - file format parser
+                 bs      - input bitstream
+
+  Explanation  : Header information is commmon to all layers. Note also that
+                 this function doesn't interprete the fields of the header.
+
+  Author(s)    : Juha Ojanpera
+  *************************************************************************/
+
+INLINE SEEK_STATUS
+decode_header(TMpTransportHandle *tHandle, TBitStream *bs)
+{
+  uint32 header, bitsLeft;
+
+  bitsLeft = (BsGetBufSize(bs) << 3) - BsGetBitsRead(bs);
+  if(bitsLeft < MAX_MP_HEADER_SIZE)
+    return (SYNC_BITS_OUT);
+
+  /*-- Read rest of the header bits. --*/
+  tHandle->headerOld.header = tHandle->header.header;
+  header = (!tHandle->mpeg25) << HEADER_BITS;
+  header |= BsGetBits(bs, HEADER_BITS);
+  tHandle->header.header = header;
+
+  /*-- Read CRC codeword. --*/
+  if(error_protection(&tHandle->header))
+    tHandle->crc.crc = (int16) BsGetBits(bs, 16);
+
+  return (SYNC_FOUND);
+}
+
+/**************************************************************************
+  Title        : GetSideInfoSlots
+
+  Purpose      : Retrieves the amount of side info for layer III stream.
+
+  Usage        : y = GetSideInfoSlots(tHandle)
+
+  Input        : tHandle - file format parser
+
+  Output       : y       - # of side info bytes
+
+  Author(s)    : Juha Ojanpera
+  *************************************************************************/
+
+int16
+GetSideInfoSlots(TMpTransportHandle *tHandle)
+{
+  int16 nSlots = 0;
+
+  if(version(&tHandle->header) != MPEG_PHASE2_LSF)
+    nSlots = (channels(&tHandle->header) == 1) ? (int16) 17 : (int16) 32;
+  else
+    nSlots = (channels(&tHandle->header) == 1) ? (int16) 9 : (int16) 17;
+
+  return (nSlots);
+}
+
+int16
+GetSideInfoSlots(TMPEG_Header *header)
+{
+  int16 nSlots = 0;
+
+  if(version(header) != MPEG_PHASE2_LSF)
+    nSlots = (channels(header) == 1) ? 17 : 32;
+  else
+    nSlots = (channels(header) == 1) ? 9 : 17;
+
+  return (nSlots);
+}
+
+/**************************************************************************
+  Title        : GetSlotSize
+
+  Purpose      : Retrieves the amount of frame data for layer III stream.
+
+  Usage        : y = GetSlotSize(tHandle)
+
+  Input        : tHandle - file format parser
+
+  Output       : y       - # of frame data bytes
+
+  Author(s)    : Juha Ojanpera
+  *************************************************************************/
+
+static INLINE int16
+GetSlotSize(TMpTransportHandle *tHandle)
+{
+  int16 ave_slots;
+  
+  if(bit_rate(&tHandle->header))
+    ave_slots = (int16) tHandle->aveFrameLen;
+  else
+  {
+    ave_slots = (int16) (tHandle->FreeFormatSlots + GetSideInfoSlots(tHandle));
+    if(error_protection(&tHandle->header))
+      ave_slots += 2;
+    ave_slots += 4;
+  }
+
+  return (ave_slots);
+}
+
+INLINE int32 *
+GetSeekOffset(TMpTransportHandle *tHandle, int32 *seekValues)
+{
+  int16 main_data;
+  int32 frameOffset, byte_offset;
+  
+  /*
+   * Some reinitialization need to be performed after file pointer has been
+   * moved to the new postion. For this reason, the total number of frames
+   * to be skipped does not correspond exactly to the given time offset.
+   * However, after reinitialization the playback position should be the correct.
+   */
+  byte_offset = GetSlotSize(tHandle);
+  main_data = (int16) ((version(&tHandle->header) == MPEG_PHASE2_LSF) ? 256 : 512);
+  frameOffset = (byte_offset) ? main_data / byte_offset : 0;
+
+  if(byte_offset)
+    if(main_data % byte_offset)
+      frameOffset++;
+
+  seekValues[0] = frameOffset;
+  seekValues[1] = byte_offset;
+
+  return (seekValues);
+}
+
+/*
+ * Estimates the bitrate of the mp3 stream from the size of the 
+ * payload + side info + header. The accuracy of the computed 
+ * bitrate depends very much on the accuracy of the average frame 
+ * size.
+ */
+int16
+MP_EstimateBitrate(TMpTransportHandle *tHandle, uint8 isVbr)
+{
+  int16 bitRate;
+
+  if(!bit_rate(&tHandle->header) || isVbr)
+  {
+    FLOAT div;
+
+    div = (FLOAT) ((version(&tHandle->header) == MPEG_PHASE2_LSF) ? 72 : 144);
+    bitRate = (int16) (((frequency(&tHandle->header) / 1000.0f) * GetSlotSize(tHandle) / div) + 0.5f);
+  }
+  else
+    bitRate = bit_rate(&tHandle->header);
+
+  return (bitRate);
+}
+
+/*
+ * Returns the length of the track in milliseconds.
+ */
+uint32
+MP_FileLengthInMs(TMpTransportHandle *tHandle, int32 fileSize)
+{
+  FLOAT frames = fileSize / (FLOAT) GetSlotSize(tHandle);
+
+  return (uint32) (frames * GetFrameTime(&tHandle->header) + 0.5f);
+}
+
+/*
+ * Returns the byte offset corresponding to the specified seeking position.
+ */
+int32
+MP_GetSeekOffset(TMpTransportHandle *tHandle, int32 seekPos)
+{
+  FLOAT numFrames;
+  int32 seekValues[2], frameOffset, byte_offset;
+
+  GetSeekOffset(tHandle, seekValues);
+
+  frameOffset = seekValues[0];
+  byte_offset = seekValues[1];
+  
+  numFrames = seekPos / (FLOAT) GetFrameTime(&tHandle->header);
+  if(numFrames < frameOffset)
+    frameOffset = 0;
+
+  /*-- Total offset. --*/
+  byte_offset = (int32) ((byte_offset * (numFrames - frameOffset)) + 0.5f);
+
+  return (byte_offset);
+}
+
+/*
+ * Returns the duration of each frame in milliseconds.
+ */
+int32
+MP_GetFrameTime(TMpTransportHandle *tHandle)
+{
+  return (GetFrameTime(&tHandle->header));
+}
+
+/*
+ * Checks if the specified mp3 stream is using free format 
+ * i.e., bitrate is not specified in the header part
+ * of the frame.
+ *
+ * Return TRUE if bitrate not specified, FALSE otherwise
+ */
+BOOL
+IsMP3FreeFormat(TMpTransportHandle *tHandle)
+{  
+  return (bit_rate(&tHandle->header) == 0);
+}
+
+/**************************************************************************
+  Title        : FillDataSlotTable
+
+  Purpose      : Pre-computes (to avoid division operation during decoding) 
+                 the payload size of layer III for all bitrates. This function
+                 should be called once the start of 1st frame has been located.
+
+  Usage        : y = FillDataSlotTable(tHandle)
+
+  Input        : tHandle - file format parser
+
+  Author(s)    : Juha Ojanpera
+  *************************************************************************/
+
+INLINE void
+FillDataSlotTable(TMpTransportHandle *tHandle)
+{
+  int16 nSlots;
+  const int16 *brTbl;
+  
+  brTbl = GetBitRateTable(&tHandle->header);
+
+  /*
+   * index 0 is free format and index 14 illegal bitrate.
+   */
+  for(int16 i = 1; i < 15; i++)
+  {
+    nSlots = (int16)((144 * brTbl[i]) / (frequency(&tHandle->header) / 1000.0f));
+
+    if(version(&tHandle->header) == MPEG_PHASE2_LSF)
+      nSlots >>= 1;
+
+    nSlots = (int16) (nSlots - GetSideInfoSlots(tHandle) - 4);
+    tHandle->SlotTable[i] = nSlots;
+  }
+}
+
+/**************************************************************************
+  Title        : SeekSync
+
+  Purpose      : Seeks for a byte aligned sync word in the bitstream and
+                 places the bitstream pointer right after the sync word.
+
+  Usage        : y = SeekSync(mp, bs_mcu, bufMapper, execState)
+
+  Input        : mp             - mp3 stream parameters
+                 bs_mcu         - bitstream parameters
+                 execState      - exec status of this function
+
+  Output       : y :
+                  SYNC_BITS_OUT - bit buffer need to be updated
+                  SYNC_LOST     - start of next frame was not found
+                  SYNC_FOUND    - OK to decode next frame
+
+  Author(s)    : Juha Ojanpera
+  *************************************************************************/
+
+INLINE SEEK_STATUS
+SeekSync(TMpTransportHandle *tHandle, TBitStream *bs_mcu, ExecState *execState)
+{
+#define PRESYNCBITS  (MP_SYNC_WORD_LENGTH + 8)
+#define POSTSYNCBITS (MAX_MP_HEADER_SIZE + 1)
+
+  uint32 hdr, bits_left;
+  BOOL exitCheck = TRUE;
+  int32 sync_cand, bits_read;
+
+  bits_left = (BsSlotsLeft(bs_mcu) - 1) << 3;
+  
+  if(execState->execMode == GLITCH_FREE && bits_left > PRESYNCBITS)
+  {
+    bits_left -= (BsByteAlign(bs_mcu) + (bits_read = tHandle->syncInfo.sync_length));
+    sync_cand = BsGetBits(bs_mcu, tHandle->syncInfo.sync_length);
+  }
+  else if(execState->execMode == GLITCH_FREE)
+  {
+    execState->execMode = GLITCH_FREE;
+
+    return (SYNC_BITS_OUT);
+  }
+  else
+  {
+    sync_cand = (int32)execState->a0_u32[0];
+    bits_read = (int32)execState->a0_u32[1];
+  }
+  
+  while(exitCheck)
+  {
+    while(sync_cand != tHandle->syncInfo.sync_word && 
+      bits_read < SYNC_THRESHOLD && bits_left)
+    {
+      bits_read++;
+      bits_left--;
+      sync_cand = (sync_cand << 1) & tHandle->syncInfo.sync_mask;
+      sync_cand |= (int16) BsGetBits(bs_mcu, 1);
+    }
+    
+    if(bits_read > SYNC_THRESHOLD)
+      return (SYNC_LOST);
+    else if(bits_left < POSTSYNCBITS)
+    {
+      execState->execMode = GLITCH0;
+      execState->a0_u32[0] = sync_cand;
+      execState->a0_u32[1] = bits_read;
+
+      return (SYNC_BITS_OUT);
+    }
+    else
+    {
+      bits_read++;
+      bits_left--;
+      sync_cand = (sync_cand << 1) & tHandle->syncInfo.sync_mask;
+      sync_cand |= (int16) BsGetBits(bs_mcu, 1);
+      
+      tHandle->mpeg25 = !(sync_cand & 0x1);
+      
+      /* Check the next frame header. */
+      hdr = (!tHandle->mpeg25) << HEADER_BITS;
+      tHandle->header.header = hdr | BsLookAhead(bs_mcu, HEADER_BITS);
+      
+      /* Detect false frame boundaries. */
+      switch(tHandle->syncInfo.sync_status)
+      {
+        case LAYER3_STREAM:
+          if(HEADER_MASK(tHandle->header.header) == HEADER_MASK(tHandle->headerOld.header) &&
+            sfreq(&tHandle->header) != 3 && LAYER_MASK(tHandle->header.header) == 0x1)
+          {
+            if(tHandle->FreeFormatSlots == 0)
+            {
+              if(bit_rate(&tHandle->header))
+                exitCheck = FALSE;
+            }
+            else exitCheck = FALSE;
+          }
+          break;
+      
+        case INIT_LAYER3_STREAM:
+          if(!(version(&tHandle->header) && mp25version(&tHandle->header)))
+          {
+            if(sfreq(&tHandle->header) != 3 && LAYER_MASK(tHandle->header.header) == 0x1 && bit_rate_idx(&tHandle->header) != 15)
+            {
+              tHandle->headerOld.header = tHandle->header.header;
+              tHandle->syncInfo.sync_status = LAYER3_STREAM;
+              exitCheck = FALSE;
+            }
+          }
+          break;
+
+        default:
+          break;
+      }
+    }
+  }  
+
+  execState->execMode = GLITCH_FREE;
+
+  return (SYNC_FOUND);
+}
+
+/**************************************************************************
+  Title        : FindFreeFormatSlotCount
+
+  Purpose      : Determines the size of the payload of a free format stream.
+
+  Usage        : y = FindFreeFormatSlotCount(mpDec, bs_mcu, execState)
+
+  Input        : mpDec     - mp3 stream parameters
+                 bs_mcu    - bitstream parameters
+                 execState - exec status of this function
+
+  Output       : y :
+                  SYNC_BITS_OUT - bit buffer need to be updated
+                  SYNC_LOST     - stream is undecodable
+                  SYNC_FOUND    - OK to start playback
+
+  Author(s)    : Juha Ojanpera
+  *************************************************************************/
+
+INLINE SEEK_STATUS
+FreeFormat(TMpTransportHandle *tHandle, TBitStream *bs_mcu, ExecState *execState)
+{
+  int16 exitCheck;
+  TMPEG_Header oldHeader;
+  uint16 sync_cand;
+  uint32 bits_read, bits_left;
+
+  tHandle->FreeFormatSlots = 0;
+  
+  if(execState->execMode == GLITCH_FREE)
+  {
+    int16 nSlots, minBytes;
+
+    nSlots = GetSideInfoSlots(tHandle);
+    minBytes = (uint16) (nSlots + 7);
+    if((BsSlotsLeft(bs_mcu) - 1) < (uint16) minBytes)
+    {
+      execState->execMode = GLITCH_FREE;
+      return (SYNC_BITS_OUT);
+    }
+
+    /*-- Read 1st header. --*/
+    decode_header(tHandle, bs_mcu);
+    oldHeader.header = tHandle->header.header;
+
+    /*-- Skip side info part. --*/
+    BsSkipNBits(bs_mcu, nSlots << 3);
+
+    sync_cand = (uint16) BsGetBits(bs_mcu, tHandle->syncInfo.sync_length);
+    bits_read = tHandle->syncInfo.sync_length;
+  }
+  else
+  {
+    sync_cand = (uint16) execState->a0_u32[0];
+    bits_read = (uint32) execState->a0_u32[1];
+    oldHeader.header = (uint32)execState->a0_u32[2];
+  }
+
+  exitCheck = 1;
+  bits_left = (BsSlotsLeft(bs_mcu) - 1) << 3;
+  //mask = (uint16) ((1 << (tHandle->syncInfo.sync_length - 1)) - 1);
+    
+  while(exitCheck)
+  {
+    while(sync_cand != tHandle->syncInfo.sync_word && bits_left)
+    {
+      bits_read++;
+      bits_left--;
+      sync_cand = (uint16) ((sync_cand << 1) & tHandle->syncInfo.sync_mask);
+      sync_cand |= (uint16) BsGetBits(bs_mcu, 1);
+    }
+
+    if(bits_left < (HEADER_BITS + 1))
+    {
+      execState->a0_u32[0] = sync_cand;
+      execState->a0_u32[1] = bits_read;
+      execState->a0_u32[2] = oldHeader.header;
+      execState->execMode = GLITCH0;
+
+      return (SYNC_BITS_OUT);
+    }
+    else
+    {
+      uint32 hdr;
+
+      bits_read++;
+      bits_left--;
+      sync_cand = (sync_cand << 1) & tHandle->syncInfo.sync_mask;
+      sync_cand |= (int16) BsGetBits(bs_mcu, 1);
+      
+      tHandle->mpeg25 = !(sync_cand & 0x1);
+      
+      /* Check the next frame header. */
+      hdr = (!tHandle->mpeg25) << HEADER_BITS;
+      tHandle->header.header = hdr | BsLookAhead(bs_mcu, HEADER_BITS);
+      
+      /* 
+       * Detect false frame boundraries. We could use header macros here
+       * to speed up the comparison but since this function is called only
+       * once (before playback/editing starts) the advantages of macros are
+       * negligible.
+       */
+      if(channels(&tHandle->header)         == channels(&oldHeader) &&
+         sfreq(&tHandle->header)            == sfreq(&oldHeader) &&
+         bit_rate(&tHandle->header)         == bit_rate(&oldHeader) &&
+         layer_number(&tHandle->header)     == layer_number(&oldHeader) &&
+         version(&tHandle->header)          == version(&oldHeader) &&
+         mode(&tHandle->header)             == mode(&oldHeader) &&
+         error_protection(&tHandle->header) == error_protection(&oldHeader))
+         exitCheck = 0;
+
+      /* The payload size cannot be determined. */
+      else if(bits_read > SYNC_THRESHOLD)     
+        return (SYNC_LOST);
+    }
+  }
+    
+  /*-- Determine the size of the payload data. --*/
+  if(bits_read != 0)
+  {
+    bits_read -= (tHandle->syncInfo.sync_length + 1);
+    tHandle->FreeFormatSlots = (int16) (bits_read >> 3);
+
+    if(padding(&oldHeader))
+      tHandle->FreeFormatSlots -= 1;
+  }
+  else
+  {
+    tHandle->FreeFormatSlots = -1;
+
+    return (SYNC_LOST);
+  }
+  
+  execState->execMode = GLITCH_FREE;
+  tHandle->transportType = GET_MPSYNC_STREAM;
+  tHandle->syncInfo.sync_status = INIT_LAYER3_STREAM;
+
+  return (SYNC_FOUND);
+}
+
+/**************************************************************************
+  Title        : mpSyncTransport
+
+  Purpose      : Sync layer interface for MPEG Layer I/II/III file formats.
+
+  Usage        : y = mpSyncTransport(tHandle, syncBuf, syncBufLen, readBits)
+
+  Input        : tHandle        - handle to MPEG Layer I/II/III parser
+                 syncBuf        - handle to sync layer buffer
+                 syncBufLen     - # of bytes present in sync layer buffer
+  
+  Output       : y              - status of operation
+                  SYNC_BITS_OUT - the sync layer buffer needs to be updated
+                  SYNC_LOST     - function failed
+                  SYNC_FOUND    - sync layer processing successfull
+                 readBits       - # of bits read from sync layer buffer
+
+  Author(s)    : Juha Ojanpera
+  *************************************************************************/
+
+
+SEEK_STATUS
+mpSyncTransport(TMpTransportHandle *tHandle, uint8 *syncBuf, 
+                uint32 syncBufLen, uint32 *readBits)
+{
+  BOOL hitExit;
+  ExecState *execState;
+  TBitStream m_Bitstream;
+  SEEK_STATUS frameStatus;
+
+  *readBits = 0;
+  hitExit = FALSE;
+  frameStatus = SYNC_LOST;
+  execState = &tHandle->execState;
+
+  BsInit(&m_Bitstream, syncBuf, syncBufLen);
+
+  if(tHandle->offsetBits)
+    BsSkipNBits(&m_Bitstream, tHandle->offsetBits);
+  tHandle->offsetBits = 0;
+
+  while(hitExit == FALSE)
+  {
+    uint32 tmp;
+    uint8 syncByte(0);
+
+    switch(tHandle->transportType)
+    {
+      case INIT_MP_STREAM:
+        frameStatus = SYNC_LOST;
+        tHandle->transportType = GET_1ST_MPSYNC_STREAM;
+        break;
+
+      case GET_1ST_MPSYNC_STREAM:
+        /*
+         * Locate sync and on succes, switch to read
+         * the headers values.
+         */
+        frameStatus = SeekSync(tHandle, &m_Bitstream, execState);
+        if((frameStatus == SYNC_FOUND) && IsMP3FreeFormat(tHandle))
+        {
+          hitExit = TRUE;
+          frameStatus = SYNC_MP3_FREE;
+          tHandle->offsetBits = (int16) (BsGetBitsRead(&m_Bitstream) & 0x7);
+        }
+        else if(frameStatus == SYNC_FOUND)
+          tHandle->transportType = GET_MPHEADER_STREAM;
+        else
+        {
+          hitExit = TRUE;
+          if(frameStatus != SYNC_LOST)
+          {
+            /*
+             * The sync search locates the syncword which is at the
+             * start of the header (1st 12 bits). Also in order to 
+             * make the search reliable, the rest of the header bits
+             * are also checked via lookahead by the sync routine.
+             * Because of this it is possible that the input buffer
+             * may run out of bits in the lookahead part. In that case
+             * the input buffer needs to be updated. The number of bytes
+             * to be updated are calculated based on the number of read 
+             * bits. Thus, in the worst case, the update process will 
+             * throw away the 1st 8 bits from the syncword. This is 
+             * something we don't want to experience since subsequent 
+             * processing relies on the fact that the whole header can 
+             * be read from the input buffer once the start of the frame 
+             * has been found. That's why we reduce the update size of the 
+             * input buffer (shown below).
+             */
+            tmp = BsGetBitsRead(&m_Bitstream);
+            syncByte = syncBuf[MAX(0, ((int32) (tmp >> 3) - 1))];
+            if((tmp & 0x7) && syncByte == 0xFF)
+            {
+              /*-- Keep the previous byte in the buffer as it may be part of header. --*/  
+              tHandle->offsetBits = (int16) (8 + (tmp & 0x7));
+
+              tmp -= 8;
+              BsClearBitsRead(&m_Bitstream);
+              BsSetBitsRead(&m_Bitstream, tmp);
+            }
+            else tHandle->offsetBits = (int16) (tmp & 0x7);
+          }
+        }
+        break;
+    
+      case GET_MPSYNC_STREAM:
+        /*
+         * Locate sync and on succes, switch to read
+         * the headers values.
+         */
+        frameStatus = SeekSync(tHandle, &m_Bitstream, execState);
+        if(frameStatus == SYNC_FOUND)
+          tHandle->transportType = GET_MPHEADER_STREAM;
+        else
+        {
+          hitExit = TRUE;
+          if(frameStatus != SYNC_LOST)
+          {
+            /*-- See explanation above. --*/
+            tmp = BsGetBitsRead(&m_Bitstream);
+            syncByte = syncBuf[MAX(0, ((int32) (tmp >> 3) - 1))];
+            if((tmp & 0x7) && syncByte == 0xFF)
+            {
+              /*-- Keep the previous byte in the buffer as it may be part of header. --*/
+              tHandle->offsetBits = (int16) (8 + (tmp & 0x7));
+
+              tmp -= 8;
+              BsClearBitsRead(&m_Bitstream);
+              BsSetBitsRead(&m_Bitstream, tmp);
+            }
+            else tHandle->offsetBits = (int16) (tmp & 0x7);
+          }
+        }
+        break;
+    
+      case GET_MPHEADER_STREAM:
+        /*
+         * Read headers values and on success, switch the state back
+         * to sync search for next frame.
+         */
+        hitExit = TRUE;
+        frameStatus = decode_header(tHandle, &m_Bitstream);
+        if(frameStatus == SYNC_FOUND)
+          tHandle->transportType = GET_MPSYNC_STREAM;
+        else if(frameStatus != SYNC_LOST)
+        {
+          /*-- Don't loose the syncword... --*/
+          tmp = BsGetBitsRead(&m_Bitstream);
+          syncByte = syncBuf[MAX(0, ((int32) (tmp >> 3) - 1))];
+          if((tmp & 0x7) && syncByte == 0xFF)
+          {
+            /*-- Keep the previous byte in the buffer as it may be part of header. --*/
+            tHandle->offsetBits = (int16) (8 + (tmp & 0x7));
+
+            tmp -= 8;
+            BsClearBitsRead(&m_Bitstream);
+            BsSetBitsRead(&m_Bitstream, tmp);
+          }
+          else tHandle->offsetBits = (int16) (tmp & 0x7);
+        }
+        break;
+    
+      default:
+        hitExit = TRUE;
+        frameStatus = SYNC_LOST;
+        break;
+    }
+  }
+
+  *readBits = BsGetBitsRead(&m_Bitstream);
+  
+  return (frameStatus);
+}
+
+/*
+ * Returns the # of bytes reserved for the Layer I/II/III payload part of current frame.
+ */
+INLINE int16
+mpGetTranportFrameLength(TMpTransportHandle *tHandle)
+{
+  int16 frameBytes;
+
+  tHandle->mainDataSlots = 0;
+
+  switch(tHandle->transportType)
+  {
+    case GET_MPSYNC_STREAM:
+    case GET_MPHEADER_STREAM:
+      tHandle->mainDataSlots = (int16) main_data_slots(tHandle);
+      frameBytes = (int16) (tHandle->mainDataSlots + GetSideInfoSlots(tHandle));
+      break;
+      
+    default:
+      frameBytes = 0;
+      break;
+  }
+  
+  return (frameBytes);
+}
+
+/*
+ * Initializes MPEG Layer I/II/III transport handle.
+ */
+void
+mpInitTransport(TMpTransportHandle *tHandle)
+{
+  ZERO_MEMORY(tHandle, sizeof(TMpTransportHandle));
+
+  tHandle->syncInfo.sync_word = (int16) SYNC_WORD;
+  tHandle->syncInfo.sync_length = (int16) MP_SYNC_WORD_LENGTH;
+  tHandle->syncInfo.sync_mask = (uint16) ((1 << tHandle->syncInfo.sync_length) - 1);
+  tHandle->syncInfo.sync_status = INIT_LAYER3_STREAM;
+  tHandle->transportType = INIT_MP_STREAM;
+  tHandle->execState.execMode = GLITCH_FREE;
+  tHandle->offsetBits = 0;
+}
+
+/**************************************************************************
+  Title        : MP_SeekSync
+
+  Purpose      : Interface to layer I/II/III frame search implementation.
+
+  Usage        : y = MP_SeekSync(tHandle, syncBuf, syncBufLen, readBytes, 
+                                 frameBytes, headerBytes, initMode)
+
+  Input        : tHandle     - layer I/II/III transport handle
+                 syncBuf     - input buffer
+                 syncBufLen  - length of 'sync_buf'
+                 initMode    - '1' when searching the 1st frame, '0' otherwise
+
+  Output       : y           - status of operation
+                 frameBytes  - # of bytes reserved for the payload part of the frame
+                 readBytes   - # of bytes read from the buffer
+                 headerBytes - # of bytes reserved for the header part of the frame
+
+  Author(s)    : Juha Ojanpera
+  *************************************************************************/
+
+int16
+MP_SeekSync(TMpTransportHandle *tHandle, uint8 *syncBuf, uint32 syncBufLen, 
+            int16 *readBytes, int16 *frameBytes, int16 *headerBytes,
+            uint8 initMode)
+{
+  uint32 readBits;
+  SEEK_STATUS syncSeekStatus;
+ 
+  syncSeekStatus = mpSyncTransport(tHandle, syncBuf, syncBufLen, &readBits);
+  if(initMode && syncSeekStatus == SYNC_FOUND)
+    FillDataSlotTable(tHandle);
+
+  *readBytes = (int16) (readBits >> 3);
+  *frameBytes = (int16) mpGetTranportFrameLength(tHandle);
+  *headerBytes = (int16) ((error_protection(&tHandle->header) ? 2 : 0) + 4);
+
+  return (int16) (syncSeekStatus);
+}
+
+/**************************************************************************
+  Title        : MP_FreeMode
+
+  Purpose      : Interface for determining the frame/payload size of free format
+                 layer III bitstream.
+
+  Usage        : y = MP_FreeMode(tHandle, syncBuf, syncBufLen, readBytes, 
+                                 frameBytes, headerBytes)
+
+  Input        : tHandle     - layer I/II/III transport handle
+                 syncBuf     - input buffer
+                 syncBufLen  - length of 'sync_buf'
+
+  Output       : y           - status of operation
+                 frameBytes  - # of bytes reserved for the payload part of the frames
+                 readBytes   - # of bytes read from the buffer
+                 headerBytes - # of bytes reserved for the header part of the frame
+
+  Author(s)    : Juha Ojanpera
+  *************************************************************************/
+
+int16
+MP_FreeMode(TMpTransportHandle *tHandle, uint8 *syncBuf, uint32 syncBufLen, 
+            int16 *readBytes, int16 *frameBytes, int16 *headerBytes)
+{
+  TBitStream m_Bitstream;
+  SEEK_STATUS syncSeekStatus;
+
+  BsInit(&m_Bitstream, syncBuf, syncBufLen);
+
+  if(tHandle->offsetBits)
+    BsSkipNBits(&m_Bitstream, tHandle->offsetBits);
+  tHandle->offsetBits = 0;
+ 
+  syncSeekStatus = FreeFormat(tHandle, &m_Bitstream, &tHandle->execState);
+  if(syncSeekStatus == SYNC_BITS_OUT)
+    tHandle->offsetBits = (int16) (BsGetBitsRead(&m_Bitstream) & 0x7);
+
+  *readBytes = (int16) (BsGetBitsRead(&m_Bitstream) >> 3);
+  *frameBytes = (int16) mpGetTranportFrameLength(tHandle);
+  *headerBytes = (int16) ((error_protection(&tHandle->header) ? 2 : 0) + 4);
+
+  return (int16) (syncSeekStatus);
+}