Ejemplo n.º 1
0
static
TRANSPORTDEC_ERROR synchronization(
        HANDLE_TRANSPORTDEC hTp,
        INT                *pHeaderBits
        )
{
  TRANSPORTDEC_ERROR err = TRANSPORTDEC_OK, errFirstFrame = TRANSPORTDEC_OK;
  HANDLE_FDK_BITSTREAM hBs = &hTp->bitStream[0];

  INT syncLayerFrameBits = 0; /* Length of sync layer frame (i.e. LOAS) */
  INT rawDataBlockLength = 0, rawDataBlockLengthPrevious;
  INT totalBits;
  INT headerBits = 0, headerBitsFirstFrame = 0, headerBitsPrevious;
  INT numFramesTraversed = 0, fTraverseMoreFrames, fConfigFound = 0, startPos, startPosFirstFrame = -1;
  INT numRawDataBlocksFirstFrame = 0, numRawDataBlocksPrevious, globalFramePosFirstFrame = 0, rawDataBlockLengthFirstFrame = 0;
  INT ignoreBufferFullness = hTp->flags & (TPDEC_IGNORE_BUFFERFULLNESS|TPDEC_SYNCOK);

  /* Synch parameters */
  INT syncLength;      /* Length of sync word in bits */
  UINT syncWord;       /* Sync word to be found */
  UINT syncMask;       /* Mask for sync word (for adding one bit, so comprising one bit less) */
  C_ALLOC_SCRATCH_START(contextFirstFrame, transportdec_parser_t, 1);

  totalBits = (INT)FDKgetValidBits(hBs);

  if (totalBits <= 0) {
    /* Return sync error, because this happens only in case of severly damaged bit streams.
       Returning TRANSPORTDEC_NOT_ENOUGH_BITS here is very dangerous. */
    /* numberOfRawDataBlocks must be always reset in case of sync errors. */
    hTp->numberOfRawDataBlocks = 0;
    goto bail;
  }

  fTraverseMoreFrames = (hTp->flags & (TPDEC_MINIMIZE_DELAY|TPDEC_EARLY_CONFIG)) && ! (hTp->flags & TPDEC_SYNCOK);

  /* Set transport specific sync parameters */
  switch (hTp->transportFmt) {
    case TT_MP4_ADTS:
      syncWord = ADTS_SYNCWORD;
      syncLength = ADTS_SYNCLENGTH;
      break;
    case TT_MP4_LOAS:
      syncWord = 0x2B7;
      syncLength = 11;
      break;
    default:
      syncWord = 0;
      syncLength = 0;
      break;
  }

  syncMask = (1<<syncLength)-1;

  do {
    INT bitsAvail = 0;     /* Bits available in bitstream buffer    */
    INT checkLengthBits;   /* Helper to check remaining bits and buffer boundaries */
    UINT synch;            /* Current sync word read from bitstream */

    headerBitsPrevious = headerBits;

    bitsAvail = (INT)FDKgetValidBits(hBs);

    if (hTp->numberOfRawDataBlocks == 0) {
      /* search synchword */

      FDK_ASSERT( (bitsAvail % TPDEC_SYNCSKIP) == 0);

      if ((bitsAvail-syncLength) < TPDEC_SYNCSKIP) {
        err = TRANSPORTDEC_NOT_ENOUGH_BITS;
        headerBits = 0;
      } else {

        synch = FDKreadBits(hBs, syncLength);

        if ( !(hTp->flags & TPDEC_SYNCOK) ) {
          for (; (bitsAvail-syncLength) >= TPDEC_SYNCSKIP; bitsAvail-=TPDEC_SYNCSKIP) {
            if (synch == syncWord) {
              break;
            }
            synch = ((synch << TPDEC_SYNCSKIP) & syncMask) | FDKreadBits(hBs, TPDEC_SYNCSKIP);
          }
        }
        if (synch != syncWord) {
          /* No correct syncword found. */
          err = TRANSPORTDEC_SYNC_ERROR;
        } else {
          err = TRANSPORTDEC_OK;
        }
        headerBits = syncLength;
      }
    } else {
      headerBits = 0;
    }

    /* Save previous raw data block data */
    rawDataBlockLengthPrevious = rawDataBlockLength;
    numRawDataBlocksPrevious = hTp->numberOfRawDataBlocks;

    /* Parse transport header (raw data block granularity) */
    startPos = FDKgetValidBits(hBs);

    if (err == TRANSPORTDEC_OK )
    {
      switch (hTp->transportFmt) {
        case TT_MP4_ADTS:
          if (hTp->numberOfRawDataBlocks <= 0)
          {
            int errC;

            /* Parse ADTS header */
            err = adtsRead_DecodeHeader( &hTp->parser.adts, &hTp->asc[0], hBs, ignoreBufferFullness );
            if (err != TRANSPORTDEC_OK) {
              if (err != TRANSPORTDEC_NOT_ENOUGH_BITS) {
                err = TRANSPORTDEC_SYNC_ERROR;
              }
            } else {
              errC = hTp->callbacks.cbUpdateConfig(hTp->callbacks.cbUpdateConfigData, &hTp->asc[0]);
              if (errC != 0) {
                err = TRANSPORTDEC_SYNC_ERROR;
              } else {
                hTp->numberOfRawDataBlocks = hTp->parser.adts.bs.num_raw_blocks+1;
                /* CAUTION: The PCE (if available) is declared to be a part of the header! */
                hTp->globalFramePos = FDKgetValidBits(hBs) + hTp->parser.adts.bs.num_pce_bits;
              }
            }
          }
          else {
            /* Reset CRC because the next bits are the beginning of a raw_data_block() */
            FDKcrcReset(&hTp->parser.adts.crcInfo);
            hTp->globalFramePos = FDKgetValidBits(hBs);
          }
          if (err == TRANSPORTDEC_OK) {
            hTp->numberOfRawDataBlocks--;
            rawDataBlockLength = adtsRead_GetRawDataBlockLength(&hTp->parser.adts, (hTp->parser.adts.bs.num_raw_blocks-hTp->numberOfRawDataBlocks));
            syncLayerFrameBits = (hTp->parser.adts.bs.frame_length<<3) - (startPos - FDKgetValidBits(hBs)) - syncLength;
            if (syncLayerFrameBits <= 0) {
              err = TRANSPORTDEC_SYNC_ERROR;
            }
          } else {
            hTp->numberOfRawDataBlocks = 0;
          }
          break;
        case TT_MP4_LOAS:
          if (hTp->numberOfRawDataBlocks <= 0)
          {
            syncLayerFrameBits = FDKreadBits(hBs, 13);
            hTp->parser.latm.m_audioMuxLengthBytes = syncLayerFrameBits;
            syncLayerFrameBits <<= 3;
          }
        case TT_MP4_LATM_MCP1:
        case TT_MP4_LATM_MCP0:
          if (hTp->numberOfRawDataBlocks <= 0)
          {
            hTp->globalFramePos = FDKgetValidBits(hBs);

            err = CLatmDemux_Read(
                    hBs,
                   &hTp->parser.latm,
                    hTp->transportFmt,
                   &hTp->callbacks,
                    hTp->asc,
                    ignoreBufferFullness);

            if (err != TRANSPORTDEC_OK) {
              if (err != TRANSPORTDEC_NOT_ENOUGH_BITS) {
                err = TRANSPORTDEC_SYNC_ERROR;
              }
            } else {
              hTp->numberOfRawDataBlocks = CLatmDemux_GetNrOfSubFrames(&hTp->parser.latm);
              syncLayerFrameBits -= startPos - FDKgetValidBits(hBs) - (13);            
            }
          } else {
            err = CLatmDemux_ReadPayloadLengthInfo(hBs, &hTp->parser.latm);
            if (err != TRANSPORTDEC_OK) {
              err = TRANSPORTDEC_SYNC_ERROR;
            }
          }
          if (err == TRANSPORTDEC_OK) {
            rawDataBlockLength = CLatmDemux_GetFrameLengthInBits(&hTp->parser.latm);
            hTp->numberOfRawDataBlocks--;
          } else {
            hTp->numberOfRawDataBlocks = 0;
          }
          break;
        default:
          {
            syncLayerFrameBits = 0;
          }
          break;
      }
    }

    headerBits += startPos - (INT)FDKgetValidBits(hBs);
    bitsAvail -= headerBits;

    checkLengthBits  = syncLayerFrameBits;

    /* Check if the whole frame would fit the bitstream buffer */
    if (err == TRANSPORTDEC_OK) {
      if ( (checkLengthBits+headerBits) > ((TRANSPORTDEC_INBUF_SIZE<<3)-7) ) {
        /* We assume that the size of the transport bit buffer has been
           chosen to meet all system requirements, thus this condition
           is considered a synchronisation error. */
        err = TRANSPORTDEC_SYNC_ERROR;
      } else {
        if ( bitsAvail < checkLengthBits ) {
          err = TRANSPORTDEC_NOT_ENOUGH_BITS;
        }
      }
    }

    if (err == TRANSPORTDEC_NOT_ENOUGH_BITS) {
      break;
    }


    if (err == TRANSPORTDEC_SYNC_ERROR) {
      int bits;

      /* Enforce re-sync of transport headers. */
      hTp->numberOfRawDataBlocks = 0;

      /* Ensure that the bit amount lands and a multiple of TPDEC_SYNCSKIP */
      bits = (bitsAvail + headerBits) % TPDEC_SYNCSKIP;
      /* Rewind - TPDEC_SYNCSKIP, in order to look for a synch one bit ahead next time. */
      FDKpushBiDirectional(hBs, -(headerBits - TPDEC_SYNCSKIP) + bits);
      bitsAvail += headerBits - TPDEC_SYNCSKIP - bits;
      headerBits = 0;      
    }

    /* Frame traversal */
    if ( fTraverseMoreFrames )
    {
      /* Save parser context for early config discovery "rewind all frames" */
      if ( (hTp->flags & TPDEC_EARLY_CONFIG) && !(hTp->flags & TPDEC_MINIMIZE_DELAY))
      {
        /* ignore buffer fullness if just traversing additional frames for ECD */
        ignoreBufferFullness = 1;

        /* Save context in order to return later */
        if ( err == TRANSPORTDEC_OK && startPosFirstFrame == -1 ) {
          startPosFirstFrame = FDKgetValidBits(hBs);
          numRawDataBlocksFirstFrame = hTp->numberOfRawDataBlocks;
          globalFramePosFirstFrame = hTp->globalFramePos;
          rawDataBlockLengthFirstFrame = rawDataBlockLength;
          headerBitsFirstFrame = headerBits;
          errFirstFrame = err;
          FDKmemcpy(contextFirstFrame, &hTp->parser, sizeof(transportdec_parser_t));
        }

        /* Break when config was found or it is not possible anymore to find a config */
        if (startPosFirstFrame != -1 && (fConfigFound || err != TRANSPORTDEC_OK)) {
          break;
        }
      }

      if (err == TRANSPORTDEC_OK) {
        FDKpushFor(hBs, rawDataBlockLength);
        bitsAvail -= rawDataBlockLength;
        numFramesTraversed++;
        /* Ignore error here itentionally. */
        transportDec_AdjustEndOfAccessUnit(hTp);
      }
    }
  } while ( fTraverseMoreFrames || (err == TRANSPORTDEC_SYNC_ERROR && !(hTp->flags & TPDEC_SYNCOK)));

  /* Restore context in case of ECD frame traversal */
  if ( startPosFirstFrame != -1 && (fConfigFound || err != TRANSPORTDEC_OK) ) {
    FDKpushBiDirectional(hBs, FDKgetValidBits(hBs) - startPosFirstFrame);
    FDKmemcpy(&hTp->parser, contextFirstFrame, sizeof(transportdec_parser_t));
    hTp->numberOfRawDataBlocks = numRawDataBlocksFirstFrame;
    hTp->globalFramePos = globalFramePosFirstFrame;
    rawDataBlockLength = rawDataBlockLengthFirstFrame;
    headerBits = headerBitsFirstFrame;
    err = errFirstFrame;
    numFramesTraversed = 0;
  } 

  /* Additional burst data mode buffer fullness check. */
  if ( !(hTp->flags & (TPDEC_IGNORE_BUFFERFULLNESS|TPDEC_SYNCOK)) && err == TRANSPORTDEC_OK) {
    err = additionalHoldOffNeeded(hTp, transportDec_GetBufferFullness(hTp), FDKgetValidBits(hBs) - syncLayerFrameBits);
    if (err == TRANSPORTDEC_NOT_ENOUGH_BITS) {
      hTp->holdOffFrames++;
    }
  }
  
  /* Rewind for retry because of not enough bits */
  if (err == TRANSPORTDEC_NOT_ENOUGH_BITS) {
    FDKpushBack(hBs, headerBits);
    headerBits = 0;
  }
  else {
    /* reset hold off frame counter */
    hTp->holdOffFrames = 0;
  }

  /* Return to last good frame in case of frame traversal but not ECD. */
  if (numFramesTraversed > 0) {
    FDKpushBack(hBs, rawDataBlockLengthPrevious);
    if (err != TRANSPORTDEC_OK) {
      hTp->numberOfRawDataBlocks = numRawDataBlocksPrevious;
      headerBits = headerBitsPrevious;
    }
    err = TRANSPORTDEC_OK;
  }

bail:
  hTp->auLength[0] = rawDataBlockLength;

  if (err == TRANSPORTDEC_OK) {
    hTp->flags |= TPDEC_SYNCOK;
  }

  if (pHeaderBits != NULL) {
    *pHeaderBits = headerBits;
  }

  if (err == TRANSPORTDEC_SYNC_ERROR) {
    hTp->flags &= ~TPDEC_SYNCOK;
  }

  C_ALLOC_SCRATCH_END(contextFirstFrame, transportdec_parser_t, 1);

  return err;
}
Ejemplo n.º 2
0
int CProgramConfig_GetElementTable(
        const CProgramConfig *pPce,
        MP4_ELEMENT_ID  elList[],
        const INT elListSize,
        UCHAR *pChMapIdx
       )
{
  int i, el = 0;

  FDK_ASSERT(elList != NULL);
  FDK_ASSERT(pChMapIdx != NULL);

  *pChMapIdx = 0;

  if ( elListSize
    < pPce->NumFrontChannelElements + pPce->NumSideChannelElements + pPce->NumBackChannelElements + pPce->NumLfeChannelElements
    )
  {
    return 0;
  }

  for (i=0; i < pPce->NumFrontChannelElements; i++)
  {
    elList[el++] = (pPce->FrontElementIsCpe[i]) ?  ID_CPE : ID_SCE;
  }

  for (i=0; i < pPce->NumSideChannelElements; i++)
  {
    elList[el++] = (pPce->SideElementIsCpe[i]) ?  ID_CPE : ID_SCE;
  }

  for (i=0; i < pPce->NumBackChannelElements; i++)
  {
    elList[el++] = (pPce->BackElementIsCpe[i]) ?  ID_CPE : ID_SCE;
  }

  for (i=0; i < pPce->NumLfeChannelElements; i++)
  {
    elList[el++] = ID_LFE;
  }


  /* Find an corresponding channel configuration if possible */
  switch (pPce->NumChannels) {
  case 1: case 2: case 3: case 4: case 5: case 6:
    /* One and two channels have no alternatives. The other ones are mapped directly to the
       corresponding channel config. Because of legacy reasons or for lack of alternative mappings. */
    *pChMapIdx = pPce->NumChannels;
    break;
  case 7:
    {
      C_ALLOC_SCRATCH_START(tmpPce, CProgramConfig, 1);
      /* Create a PCE for the config to test ... */
      CProgramConfig_GetDefault(tmpPce, 11);
      /* ... and compare it with the given one. */
      *pChMapIdx = (!(CProgramConfig_Compare(pPce, tmpPce)&0xE)) ? 11 : 0;
      /* If compare result is 0 or 1 we can be sure that it is channel config 11. */
      C_ALLOC_SCRATCH_END(tmpPce, CProgramConfig, 1);
    }
    break;
  case 8:
    { /* Try the four possible 7.1ch configurations. One after the other. */
      UCHAR testCfg[4] = { 32, 14, 12, 7};
      C_ALLOC_SCRATCH_START(tmpPce, CProgramConfig, 1);
      for (i=0; i<4; i+=1) {
        /* Create a PCE for the config to test ... */
        CProgramConfig_GetDefault(tmpPce, testCfg[i]);
        /* ... and compare it with the given one. */
        if (!(CProgramConfig_Compare(pPce, tmpPce)&0xE)) {
          /* If the compare result is 0 or 1 than the two channel configurations match. */
          /* Explicit mapping of 7.1 side channel configuration to 7.1 rear channel mapping. */
          *pChMapIdx = (testCfg[i]==32) ? 12 : testCfg[i];
        }
      }
      C_ALLOC_SCRATCH_END(tmpPce, CProgramConfig, 1);
    }
    break;
  default:
    /* The PCE does not match any predefined channel configuration. */
    *pChMapIdx = 0;
    break;
  }

  return el;
}
Ejemplo n.º 3
0
static
TRANSPORTDEC_ERROR synchronization(
        HANDLE_TRANSPORTDEC hTp,
        INT                *pHeaderBits
        )
{
  TRANSPORTDEC_ERROR err = TRANSPORTDEC_OK, errFirstFrame = TRANSPORTDEC_OK;
  HANDLE_FDK_BITSTREAM hBs = &hTp->bitStream[0];

  INT syncLayerFrameBits = 0; /* Length of sync layer frame (i.e. LOAS) */
  INT rawDataBlockLength = 0, rawDataBlockLengthPrevious;
  INT totalBits;
  INT headerBits = 0, headerBitsFirstFrame = 0, headerBitsPrevious;
  INT numFramesTraversed = 0, fTraverseMoreFrames, fConfigFound = (hTp->flags & TPDEC_CONFIG_FOUND), startPosFirstFrame = -1;
  INT numRawDataBlocksFirstFrame = 0, numRawDataBlocksPrevious, globalFramePosFirstFrame = 0, rawDataBlockLengthFirstFrame = 0;
  INT ignoreBufferFullness = hTp->flags & (TPDEC_LOST_FRAMES_PENDING|TPDEC_IGNORE_BUFFERFULLNESS|TPDEC_SYNCOK);

  /* Synch parameters */
  INT syncLength;      /* Length of sync word in bits */
  UINT syncWord;       /* Sync word to be found */
  UINT syncMask;       /* Mask for sync word (for adding one bit, so comprising one bit less) */
  C_ALLOC_SCRATCH_START(contextFirstFrame, transportdec_parser_t, 1);

  totalBits = (INT)FDKgetValidBits(hBs);

  if (totalBits <= 0) {
    err = TRANSPORTDEC_NOT_ENOUGH_BITS;
    goto bail;
  }

  fTraverseMoreFrames = (hTp->flags & (TPDEC_MINIMIZE_DELAY|TPDEC_EARLY_CONFIG)) && ! (hTp->flags & TPDEC_SYNCOK);

  /* Set transport specific sync parameters */
  switch (hTp->transportFmt) {
    case TT_MP4_ADTS:
      syncWord = ADTS_SYNCWORD;
      syncLength = ADTS_SYNCLENGTH;
      break;
    case TT_MP4_LOAS:
      syncWord = 0x2B7;
      syncLength = 11;
      break;
    default:
      syncWord = 0;
      syncLength = 0;
      break;
  }

  syncMask = (1<<syncLength)-1;

  do {
    INT bitsAvail = 0;     /* Bits available in bitstream buffer    */
    INT checkLengthBits;   /* Helper to check remaining bits and buffer boundaries */
    UINT synch;            /* Current sync word read from bitstream */

    headerBitsPrevious = headerBits;

    bitsAvail = (INT)FDKgetValidBits(hBs);

    if (hTp->numberOfRawDataBlocks == 0) {
      /* search synchword */

      FDK_ASSERT( (bitsAvail % TPDEC_SYNCSKIP) == 0);

      if ((bitsAvail-syncLength) < TPDEC_SYNCSKIP) {
        err = TRANSPORTDEC_NOT_ENOUGH_BITS;
        headerBits = 0;
      } else {

        synch = FDKreadBits(hBs, syncLength);

        if ( !(hTp->flags & TPDEC_SYNCOK) ) {
          for (; (bitsAvail-syncLength) >= TPDEC_SYNCSKIP; bitsAvail-=TPDEC_SYNCSKIP) {
            if (synch == syncWord) {
              break;
            }
            synch = ((synch << TPDEC_SYNCSKIP) & syncMask) | FDKreadBits(hBs, TPDEC_SYNCSKIP);
          }
        }
        if (synch != syncWord) {
          /* No correct syncword found. */
          err = TRANSPORTDEC_SYNC_ERROR;
        } else {
          err = TRANSPORTDEC_OK;
        }
        headerBits = syncLength;
      }
    } else {
      headerBits = 0;
    }

    /* Save previous raw data block data */
    rawDataBlockLengthPrevious = rawDataBlockLength;
    numRawDataBlocksPrevious = hTp->numberOfRawDataBlocks;

    /* Parse transport header (raw data block granularity) */

    if (err == TRANSPORTDEC_OK )
    {
      err = transportDec_readHeader(
              hTp,
              hBs,
              syncLength,
              ignoreBufferFullness,
             &rawDataBlockLength,
             &fTraverseMoreFrames,
             &syncLayerFrameBits,
             &fConfigFound,
             &headerBits
              );
    }

    bitsAvail -= headerBits;

    checkLengthBits  = syncLayerFrameBits;

    /* Check if the whole frame would fit the bitstream buffer */
    if (err == TRANSPORTDEC_OK) {
      if ( (checkLengthBits+headerBits) > ((TRANSPORTDEC_INBUF_SIZE<<3)-7) ) {
        /* We assume that the size of the transport bit buffer has been
           chosen to meet all system requirements, thus this condition
           is considered a synchronisation error. */
        err = TRANSPORTDEC_SYNC_ERROR;
      } else {
        if ( bitsAvail < checkLengthBits ) {
          err = TRANSPORTDEC_NOT_ENOUGH_BITS;
        }
      }
    }

    if (err == TRANSPORTDEC_NOT_ENOUGH_BITS) {
      break;
    }


    if (err == TRANSPORTDEC_SYNC_ERROR) {
      int bits;

      /* Enforce re-sync of transport headers. */
      hTp->numberOfRawDataBlocks = 0;

      /* Ensure that the bit amount lands at a multiple of TPDEC_SYNCSKIP */
      bits = (bitsAvail + headerBits) % TPDEC_SYNCSKIP;
      /* Rewind - TPDEC_SYNCSKIP, in order to look for a synch one bit ahead next time. */
      FDKpushBiDirectional(hBs, -(headerBits - TPDEC_SYNCSKIP) + bits);
      bitsAvail += headerBits - TPDEC_SYNCSKIP - bits;
      headerBits = 0;
    }

    /* Frame traversal */
    if ( fTraverseMoreFrames )
    {
      /* Save parser context for early config discovery "rewind all frames" */
      if ( (hTp->flags & TPDEC_EARLY_CONFIG) && !(hTp->flags & TPDEC_MINIMIZE_DELAY))
      {
        /* ignore buffer fullness if just traversing additional frames for ECD */
        ignoreBufferFullness = 1;

        /* Save context in order to return later */
        if ( err == TRANSPORTDEC_OK && startPosFirstFrame == -1 ) {
          startPosFirstFrame = FDKgetValidBits(hBs);
          numRawDataBlocksFirstFrame = hTp->numberOfRawDataBlocks;
          globalFramePosFirstFrame = hTp->globalFramePos;
          rawDataBlockLengthFirstFrame = rawDataBlockLength;
          headerBitsFirstFrame = headerBits;
          errFirstFrame = err;
          FDKmemcpy(contextFirstFrame, &hTp->parser, sizeof(transportdec_parser_t));
        }

        /* Break when config was found or it is not possible anymore to find a config */
        if (startPosFirstFrame != -1 && (fConfigFound || err != TRANSPORTDEC_OK))
        {
          /* In case of ECD and sync error, do not rewind anywhere. */
          if (err == TRANSPORTDEC_SYNC_ERROR)
          {
            startPosFirstFrame = -1;
            fConfigFound = 0;
            numFramesTraversed = 0;
          }
          break;
        }
      }

      if (err == TRANSPORTDEC_OK) {
        FDKpushFor(hBs, rawDataBlockLength);
        bitsAvail -= rawDataBlockLength;
        numFramesTraversed++;
        /* Ignore error here itentionally. */
        transportDec_AdjustEndOfAccessUnit(hTp);
      }
    }
  } while ( fTraverseMoreFrames || (err == TRANSPORTDEC_SYNC_ERROR && !(hTp->flags & TPDEC_SYNCOK)));

  /* Restore context in case of ECD frame traversal */
  if ( startPosFirstFrame != -1 && (fConfigFound || err != TRANSPORTDEC_OK) ) {
    FDKpushBiDirectional(hBs, FDKgetValidBits(hBs) - startPosFirstFrame);
    FDKmemcpy(&hTp->parser, contextFirstFrame, sizeof(transportdec_parser_t));
    hTp->numberOfRawDataBlocks = numRawDataBlocksFirstFrame;
    hTp->globalFramePos = globalFramePosFirstFrame;
    rawDataBlockLength = rawDataBlockLengthFirstFrame;
    headerBits = headerBitsFirstFrame;
    err = errFirstFrame;
    numFramesTraversed = 0;
  } 

  /* Additional burst data mode buffer fullness check. */
  if ( !(hTp->flags & (TPDEC_LOST_FRAMES_PENDING|TPDEC_IGNORE_BUFFERFULLNESS|TPDEC_SYNCOK)) && err == TRANSPORTDEC_OK) {
    err = additionalHoldOffNeeded(hTp, transportDec_GetBufferFullness(hTp), FDKgetValidBits(hBs) - syncLayerFrameBits);
    if (err == TRANSPORTDEC_NOT_ENOUGH_BITS) {
      hTp->holdOffFrames++;
    }
  }
  
  /* Rewind for retry because of not enough bits */
  if (err == TRANSPORTDEC_NOT_ENOUGH_BITS) {
    FDKpushBack(hBs, headerBits);
    headerBits = 0;
  }
  else {
    /* reset hold off frame counter */
    hTp->holdOffFrames = 0;
  }

  /* Return to last good frame in case of frame traversal but not ECD. */
  if (numFramesTraversed > 0) {
    FDKpushBack(hBs, rawDataBlockLengthPrevious);
    if (err != TRANSPORTDEC_OK) {
      hTp->numberOfRawDataBlocks = numRawDataBlocksPrevious;
      headerBits = headerBitsPrevious;
    }
    err = TRANSPORTDEC_OK;
  }

bail:
  hTp->auLength[0] = rawDataBlockLength;

  /* Detect pointless TRANSPORTDEC_NOT_ENOUGH_BITS error case, were the bit buffer is already full,
     or no new burst packet fits. Recover by advancing the bit buffer. */
  if ( (TRANSPORTDEC_NOT_ENOUGH_BITS == err) &&  (FDKgetValidBits(hBs) >= ((TRANSPORTDEC_INBUF_SIZE*8 - ((hTp->avgBitRate*hTp->burstPeriod)/1000)) - 7)) )
  {
    FDKpushFor(hBs, TPDEC_SYNCSKIP);
    err = TRANSPORTDEC_SYNC_ERROR;
  }

  if (err == TRANSPORTDEC_OK) {
    hTp->flags |= TPDEC_SYNCOK;
  }

  if (fConfigFound) {
    hTp->flags |= TPDEC_CONFIG_FOUND;
  }

  if (pHeaderBits != NULL) {
    *pHeaderBits = headerBits;
  }

  if (err == TRANSPORTDEC_SYNC_ERROR) {
    hTp->flags &= ~TPDEC_SYNCOK;
  }

  C_ALLOC_SCRATCH_END(contextFirstFrame, transportdec_parser_t, 1);

  return err;
}
Ejemplo n.º 4
0
void
FDKaacEnc_groupShortData(FIXP_DBL      *mdctSpectrum,     /* in-out                           */
               SFB_THRESHOLD *sfbThreshold,     /* in-out                           */
               SFB_ENERGY    *sfbEnergy,        /* in-out                           */
               SFB_ENERGY    *sfbEnergyMS,      /* in-out                           */
               SFB_ENERGY    *sfbSpreadEnergy,
               const INT      sfbCnt,
               const INT      sfbActive,
               const INT     *sfbOffset,
               const FIXP_DBL *sfbMinSnrLdData,
               INT           *groupedSfbOffset,       /* out */
               INT           *maxSfbPerGroup,         /* out */
               FIXP_DBL      *groupedSfbMinSnrLdData,
               const INT      noOfGroups,
               const INT     *groupLen,
               const INT      granuleLength)
{
  INT i,j;
  INT line;       /* counts through lines              */
  INT sfb;        /* counts through scalefactor bands  */
  INT grp;        /* counts through groups             */
  INT wnd;        /* counts through windows in a group */
  INT offset;     /* needed in sfbOffset grouping      */
  INT highestSfb;

  INT granuleLength_short = granuleLength/TRANS_FAC;

  /* for short blocks: regroup spectrum and */
  /* group energies and thresholds according to grouping */
  C_ALLOC_SCRATCH_START(tmpSpectrum, FIXP_DBL, (1024));

  /* calculate maxSfbPerGroup */
  highestSfb = 0;
  for (wnd = 0; wnd < TRANS_FAC; wnd++)
  {
    for (sfb = sfbActive-1; sfb >= highestSfb; sfb--)
    {
      for (line = sfbOffset[sfb+1]-1; line >= sfbOffset[sfb]; line--)
      {
        if ( mdctSpectrum[wnd*granuleLength_short+line] != FL2FXCONST_SPC(0.0) ) break; /* this band is not completely zero */
      }
      if (line >= sfbOffset[sfb]) break;                                      /* this band was not completely zero */
    }
    highestSfb = fixMax(highestSfb, sfb);
  }
  highestSfb = highestSfb > 0 ? highestSfb : 0;
  *maxSfbPerGroup = highestSfb+1;

  /* calculate groupedSfbOffset */
  i = 0;
  offset = 0;
  for (grp = 0; grp < noOfGroups; grp++)
  {
      for (sfb = 0; sfb < sfbActive+1; sfb++)
      {
          groupedSfbOffset[i++] = offset + sfbOffset[sfb] * groupLen[grp];
      }
      i +=  sfbCnt-sfb;
      offset += groupLen[grp] * granuleLength_short;
  }
  groupedSfbOffset[i++] = granuleLength;

  /* calculate groupedSfbMinSnr */
  i = 0;
  for (grp = 0; grp < noOfGroups; grp++)
  {
    for (sfb = 0; sfb < sfbActive; sfb++)
    {
      groupedSfbMinSnrLdData[i++] = sfbMinSnrLdData[sfb];
    }
    i +=  sfbCnt-sfb;
  }

  /* sum up sfbThresholds */
  wnd = 0;
  i = 0;
  for (grp = 0; grp < noOfGroups; grp++)
  {
    for (sfb = 0; sfb < sfbActive; sfb++)
    {
      FIXP_DBL thresh = sfbThreshold->Short[wnd][sfb];
      for (j=1; j<groupLen[grp]; j++)
      {
        thresh = nrgAddSaturate(thresh, sfbThreshold->Short[wnd+j][sfb]);
      }
      sfbThreshold->Long[i++] = thresh;
    }
    i +=  sfbCnt-sfb;
    wnd += groupLen[grp];
  }

  /* sum up sfbEnergies left/right */
  wnd = 0;
  i = 0;
  for (grp = 0; grp < noOfGroups; grp++)
  {
    for (sfb = 0; sfb < sfbActive; sfb++)
    {
      FIXP_DBL energy = sfbEnergy->Short[wnd][sfb];
      for (j=1; j<groupLen[grp]; j++)
      {
        energy = nrgAddSaturate(energy, sfbEnergy->Short[wnd+j][sfb]);
      }
      sfbEnergy->Long[i++] = energy;
    }
    i +=  sfbCnt-sfb;
    wnd += groupLen[grp];
  }

  /* sum up sfbEnergies mid/side */
  wnd = 0;
  i = 0;
  for (grp = 0; grp < noOfGroups; grp++)
  {
    for (sfb = 0; sfb < sfbActive; sfb++)
    {
      FIXP_DBL energy = sfbEnergyMS->Short[wnd][sfb];
      for (j=1; j<groupLen[grp]; j++)
      {
        energy = nrgAddSaturate(energy, sfbEnergyMS->Short[wnd+j][sfb]);
      }
      sfbEnergyMS->Long[i++] = energy;
    }
    i +=  sfbCnt-sfb;
    wnd += groupLen[grp];
  }

  /* sum up sfbSpreadEnergies */
  wnd = 0;
  i = 0;
  for (grp = 0; grp < noOfGroups; grp++)
  {
    for (sfb = 0; sfb < sfbActive; sfb++)
    {
      FIXP_DBL energy = sfbSpreadEnergy->Short[wnd][sfb];
      for (j=1; j<groupLen[grp]; j++)
      {
         energy = nrgAddSaturate(energy, sfbSpreadEnergy->Short[wnd+j][sfb]);
      }
      sfbSpreadEnergy->Long[i++] = energy;
    }
    i +=  sfbCnt-sfb;
    wnd += groupLen[grp];
  }

  /* re-group spectrum */
  wnd = 0;
  i = 0;
  for (grp = 0; grp < noOfGroups; grp++)
  {
    for (sfb = 0; sfb < sfbActive; sfb++)
    {
      int width = sfbOffset[sfb+1]-sfbOffset[sfb];
      FIXP_DBL *pMdctSpectrum = &mdctSpectrum[sfbOffset[sfb]] + wnd*granuleLength_short;
      for (j = 0; j < groupLen[grp]; j++)
      {
        FIXP_DBL *pTmp = pMdctSpectrum;
        for (line = width; line > 0; line--)
        {
          tmpSpectrum[i++] = *pTmp++;
        }
        pMdctSpectrum += granuleLength_short;
      }
    }
    i +=  (groupLen[grp]*(sfbOffset[sfbCnt]-sfbOffset[sfb]));
    wnd += groupLen[grp];
  }

  FDKmemcpy(mdctSpectrum, tmpSpectrum, granuleLength*sizeof(FIXP_DBL));

  C_ALLOC_SCRATCH_END(tmpSpectrum, FIXP_DBL, (1024))
}
Ejemplo n.º 5
0
static void CTns_Filter (FIXP_DBL *spec, int size, int inc, FIXP_TCC coeff [], int order)
{
  // - Simple all-pole filter of order "order" defined by
  //   y(n) =  x(n) - a(2)*y(n-1) - ... - a(order+1)*y(n-order)
  //
  // - The state variables of the filter are initialized to zero every time
  //
  // - The output data is written over the input data ("in-place operation")
  //
  // - An input vector of "size" samples is processed and the index increment
  //   to the next data sample is given by "inc"

  int i,j,N;
  FIXP_DBL *pSpec;
  FIXP_DBL maxVal=FL2FXCONST_DBL(0.0);
  INT s;

  FDK_ASSERT(order <= TNS_MAXIMUM_ORDER);
  C_ALLOC_SCRATCH_START(state, FIXP_DBL, TNS_MAXIMUM_ORDER);
  FDKmemclear(state, order*sizeof(FIXP_DBL));

  for (i=0; i<size; i++) {
    maxVal = fixMax(maxVal,fixp_abs(spec[i]));
  }

  if ( maxVal > FL2FXCONST_DBL(0.03125*0.70710678118) )
    s = fixMax(CntLeadingZeros(maxVal)-6,0);
  else
    s = fixMax(CntLeadingZeros(maxVal)-5,0);

  s = fixMin(s,2);
  s = s-1;

  if (inc == -1)
    pSpec = &spec[size - 1];
  else
    pSpec = &spec[0];

  FIXP_TCC *pCoeff;

#define FIRST_PART_FLTR                                              \
    FIXP_DBL x, *pState = state;                                     \
    pCoeff = coeff;                                                  \
                                                                     \
    if (s < 0)                                                       \
      x = (pSpec [0]>>1) + fMultDiv2 (*pCoeff++, pState [0]) ;       \
    else                                                             \
      x = (pSpec [0]<<s) + fMultDiv2 (*pCoeff++, pState [0]) ;

#define INNER_FLTR_INLINE                                            \
      x = fMultAddDiv2 (x, *pCoeff, pState [1]);                     \
      pState [0] = pState [1] - (fMultDiv2 (*pCoeff++, x) <<2) ;     \
      pState++;

#define LAST_PART_FLTR                                               \
      if (s < 0)                                                     \
        *pSpec = x << 1;                                             \
      else                                                           \
        *pSpec = x >> s;                                             \
      *pState =(-x) << 1;                                            \
      pSpec   += inc ;


   if (order>8)
   {
      N = (order-1)&7;

      for (i = size ; i != 0 ; i--)
      {
        FIRST_PART_FLTR

        for (j = N; j > 0 ; j--) { INNER_FLTR_INLINE }

        INNER_FLTR_INLINE INNER_FLTR_INLINE INNER_FLTR_INLINE INNER_FLTR_INLINE
        INNER_FLTR_INLINE INNER_FLTR_INLINE INNER_FLTR_INLINE INNER_FLTR_INLINE

        LAST_PART_FLTR
      }

   } else if (order>4) {