Пример #1
0
TRANSPORTDEC_ERROR adifRead_DecodeHeader(
        CAdifHeader          *pAdifHeader,
        CProgramConfig       *pPce,
        HANDLE_FDK_BITSTREAM  bs
        )
{
  int i;
  TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK;
  UINT startAnchor = FDKgetValidBits(bs);

  if ((INT)startAnchor < MIN_ADIF_HEADERLENGTH) {
    return (TRANSPORTDEC_NOT_ENOUGH_BITS);
  }

  if (FDKreadBits(bs,8) != 'A') {
    return (TRANSPORTDEC_SYNC_ERROR);
  }
  if (FDKreadBits(bs,8) != 'D') {
    return (TRANSPORTDEC_SYNC_ERROR);
  }
  if (FDKreadBits(bs,8) != 'I') {
    return (TRANSPORTDEC_SYNC_ERROR);
  }
  if (FDKreadBits(bs,8) != 'F') {
    return (TRANSPORTDEC_SYNC_ERROR);
  }

  if ( (pAdifHeader->CopyrightIdPresent = FDKreadBits(bs,1)) != 0 )
    FDKpushBiDirectional(bs,72);  /* CopyrightId */


  pAdifHeader->OriginalCopy = FDKreadBits(bs,1);
  pAdifHeader->Home = FDKreadBits(bs,1);
  pAdifHeader->BitstreamType = FDKreadBits(bs,1);

  /* pAdifHeader->BitRate = FDKreadBits(bs, 23); */
  pAdifHeader->BitRate = FDKreadBits(bs,16);
  pAdifHeader->BitRate <<= 7;
  pAdifHeader->BitRate |= FDKreadBits(bs,7);

  pAdifHeader->NumProgramConfigElements = FDKreadBits(bs,4) + 1;

  if (pAdifHeader->BitstreamType == 0) {
    FDKpushBiDirectional(bs,20);  /* adif_buffer_fullness */
  }

  /* Parse all PCEs but keep only one */
  for (i=0; i < pAdifHeader->NumProgramConfigElements; i++)
  {
    CProgramConfig_Read(pPce, bs, startAnchor);
  }

  FDKbyteAlign(bs, startAnchor);

  return (ErrorStatus);
}
Пример #2
0
/*
 * Read the extension for height info.
 * return 0 if successfull or -1 if the CRC failed.
 */
static
int CProgramConfig_ReadHeightExt(
                                  CProgramConfig *pPce,
                                  HANDLE_FDK_BITSTREAM bs,
                                  int * const bytesAvailable,
                                  const UINT alignmentAnchor
                                )
{
  int err = 0;
  FDK_CRCINFO crcInfo;    /* CRC state info */
  INT crcReg;
  FDKcrcInit(&crcInfo, 0x07, 0xFF, 8);
  crcReg = FDKcrcStartReg(&crcInfo, bs, 0);
  UINT startAnchor = FDKgetValidBits(bs);

  FDK_ASSERT(pPce != NULL);
  FDK_ASSERT(bs != NULL);
  FDK_ASSERT(bytesAvailable != NULL);

  if ( (startAnchor >= 24) && (*bytesAvailable >= 3)
    && (FDKreadBits(bs,8) == PCE_HEIGHT_EXT_SYNC) )
  {
    int i;

    for (i=0; i < pPce->NumFrontChannelElements; i++)
    {
      pPce->FrontElementHeightInfo[i] = (UCHAR) FDKreadBits(bs,2);
    }
    for (i=0; i < pPce->NumSideChannelElements; i++)
    {
      pPce->SideElementHeightInfo[i] = (UCHAR) FDKreadBits(bs,2);
    }
    for (i=0; i < pPce->NumBackChannelElements; i++)
    {
      pPce->BackElementHeightInfo[i] = (UCHAR) FDKreadBits(bs,2);
    }
    FDKbyteAlign(bs, alignmentAnchor);

    FDKcrcEndReg(&crcInfo, bs, crcReg);
    if ((USHORT)FDKreadBits(bs,8) != FDKcrcGetCRC(&crcInfo)) {
      /* CRC failed */
      err = -1;
    }
  }
  else {
    /* No valid extension data found -> restore the initial bitbuffer state */
    FDKpushBack(bs, startAnchor - FDKgetValidBits(bs));
  }

  /* Always report the bytes read. */
  *bytesAvailable -= (startAnchor - FDKgetValidBits(bs)) >> 3;

  return (err);
}
Пример #3
0
/**
 * \brief adjust bit stream position and the end of an access unit.
 * \param hTp transport decoder handle.
 * \return error code.
 */
static
TRANSPORTDEC_ERROR transportDec_AdjustEndOfAccessUnit(HANDLE_TRANSPORTDEC hTp)
{
  HANDLE_FDK_BITSTREAM hBs = &hTp->bitStream[0];
  TRANSPORTDEC_ERROR err = TRANSPORTDEC_OK;

  switch (hTp->transportFmt) {
    case TT_MP4_LOAS:
    case TT_MP4_LATM_MCP0:
    case TT_MP4_LATM_MCP1:
      if ( hTp->numberOfRawDataBlocks == 0 )
      {
        /* Check global frame length */
        if (hTp->transportFmt == TT_MP4_LOAS && hTp->parser.latm.m_audioMuxLengthBytes > 0)
        {
          int loasOffset;

          loasOffset = (hTp->parser.latm.m_audioMuxLengthBytes*8 + FDKgetValidBits(hBs)) - hTp->globalFramePos;
          if (loasOffset != 0) {
            FDKpushBiDirectional(hBs, loasOffset);
            /* For ELD and other payloads there is an unknown amount of padding, so ignore unread bits, but
               throw an error only if too many bits where read. */
            if (loasOffset < 0) {
              err = TRANSPORTDEC_PARSE_ERROR;
            }
          }
        }

        /* Do global LOAS/LATM audioMuxElement byte alignment */
        FDKbyteAlign(hBs, hTp->globalFramePos);
      }
      break;
    default:
      break;
  }

  return err;
}
Пример #4
0
void CProgramConfig_Read(
                          CProgramConfig *pPce,
                          HANDLE_FDK_BITSTREAM bs,
                          UINT alignmentAnchor
                        )
{
  int i, err = 0;
  int commentBytes;

  pPce->NumEffectiveChannels = 0;
  pPce->NumChannels = 0;
  pPce->ElementInstanceTag = (UCHAR) FDKreadBits(bs,4);
  pPce->Profile = (UCHAR) FDKreadBits(bs,2);
  pPce->SamplingFrequencyIndex = (UCHAR) FDKreadBits(bs,4);
  pPce->NumFrontChannelElements = (UCHAR) FDKreadBits(bs,4);
  pPce->NumSideChannelElements = (UCHAR) FDKreadBits(bs,4);
  pPce->NumBackChannelElements = (UCHAR) FDKreadBits(bs,4);
  pPce->NumLfeChannelElements = (UCHAR) FDKreadBits(bs,2);
  pPce->NumAssocDataElements = (UCHAR) FDKreadBits(bs,3);
  pPce->NumValidCcElements = (UCHAR) FDKreadBits(bs,4);

  if ((pPce->MonoMixdownPresent = (UCHAR) FDKreadBits(bs,1)) != 0)
  {
    pPce->MonoMixdownElementNumber = (UCHAR) FDKreadBits(bs,4);
  }

  if ((pPce->StereoMixdownPresent = (UCHAR) FDKreadBits(bs,1)) != 0)
  {
    pPce->StereoMixdownElementNumber = (UCHAR) FDKreadBits(bs,4);
  }

  if ((pPce->MatrixMixdownIndexPresent = (UCHAR) FDKreadBits(bs,1)) != 0)
  {
    pPce->MatrixMixdownIndex = (UCHAR) FDKreadBits(bs,2);
    pPce->PseudoSurroundEnable = (UCHAR) FDKreadBits(bs,1);
  }

  for (i=0; i < pPce->NumFrontChannelElements; i++)
  {
    pPce->FrontElementIsCpe[i] = (UCHAR) FDKreadBits(bs,1);
    pPce->FrontElementTagSelect[i] = (UCHAR) FDKreadBits(bs,4);
    pPce->NumChannels += pPce->FrontElementIsCpe[i] ? 2 : 1;
  }

  for (i=0; i < pPce->NumSideChannelElements; i++)
  {
    pPce->SideElementIsCpe[i] = (UCHAR) FDKreadBits(bs,1);
    pPce->SideElementTagSelect[i] = (UCHAR) FDKreadBits(bs,4);
    pPce->NumChannels += pPce->SideElementIsCpe[i] ? 2 : 1;
  }

  for (i=0; i < pPce->NumBackChannelElements; i++)
  {
    pPce->BackElementIsCpe[i] = (UCHAR) FDKreadBits(bs,1);
    pPce->BackElementTagSelect[i] = (UCHAR) FDKreadBits(bs,4);
    pPce->NumChannels += pPce->BackElementIsCpe[i] ? 2 : 1;
  }

  pPce->NumEffectiveChannels = pPce->NumChannels;

  for (i=0; i < pPce->NumLfeChannelElements; i++)
  {
    pPce->LfeElementTagSelect[i] = (UCHAR) FDKreadBits(bs,4);
    pPce->NumChannels += 1;
  }

  for (i=0; i < pPce->NumAssocDataElements; i++)
  {
    pPce->AssocDataElementTagSelect[i] = (UCHAR) FDKreadBits(bs,4);
  }

  for (i=0; i < pPce->NumValidCcElements; i++)
  {
    pPce->CcElementIsIndSw[i] = (UCHAR) FDKreadBits(bs,1);
    pPce->ValidCcElementTagSelect[i] = (UCHAR) FDKreadBits(bs,4);
  }

  FDKbyteAlign(bs, alignmentAnchor);

  pPce->CommentFieldBytes = (UCHAR) FDKreadBits(bs,8);
  commentBytes = pPce->CommentFieldBytes;

  /* Search for height info extension and read it if available */
  err = CProgramConfig_ReadHeightExt( pPce, bs, &commentBytes, alignmentAnchor );

  for (i=0; i < commentBytes; i++)
  {
    UCHAR text;

    text = (UCHAR)FDKreadBits(bs,8);

    if (i < PC_COMMENTLENGTH)
    {
      pPce->Comment[i] = text;
    }
  }

  pPce->isValid = (err) ? 0 : 1;
}
int transportEnc_writePCE(HANDLE_FDK_BITSTREAM hBs,
                          CHANNEL_MODE channelMode,
                          INT sampleRate,
                          int instanceTagPCE,
                          int profile,
                          int matrixMixdownA,
                          int pseudoSurroundEnable,
                          UINT alignAnchor)
{
  int sampleRateIndex, i;
  const PCE_CONFIGURATION* config = NULL;
  const MP4_ELEMENT_ID* pEl_list = NULL;
  UCHAR cpeCnt=0, sceCnt=0, lfeCnt=0;

  sampleRateIndex = getSamplingRateIndex(sampleRate);
  if (sampleRateIndex == 15) {
    return -1;
  }

  if ((config=getPceEntry(channelMode))==NULL) {
    return -1;
  }

  /* Pointer to first element in element list. */
  pEl_list = &config->el_list[0];

  FDKwriteBits(hBs, instanceTagPCE,  4);                        /* Element instance tag */
  FDKwriteBits(hBs, profile,         2);                        /* Object type */
  FDKwriteBits(hBs, sampleRateIndex, 4);                        /* Sample rate index*/

  FDKwriteBits(hBs, config->num_front_channel_elements, 4);     /* Front channel Elements */
  FDKwriteBits(hBs, config->num_side_channel_elements , 4);     /* No Side Channel Elements */
  FDKwriteBits(hBs, config->num_back_channel_elements , 4);     /* No Back channel Elements */
  FDKwriteBits(hBs, config->num_lfe_channel_elements  , 2);     /* No Lfe channel elements */

  FDKwriteBits(hBs, 0, 3);                                      /* No assoc data elements */
  FDKwriteBits(hBs, 0, 4);                                      /* No valid cc elements */
  FDKwriteBits(hBs, 0, 1);                                      /* Mono mixdown present */
  FDKwriteBits(hBs, 0, 1);                                      /* Stereo mixdown present */

  if ( matrixMixdownA!=0 && ((channelMode==MODE_1_2_2)||(channelMode==MODE_1_2_2_1)) ) {
      FDKwriteBits(hBs, 1, 1);                                  /* Matrix mixdown present */
      FDKwriteBits(hBs, (matrixMixdownA-1)&0x3, 2);             /* matrix_mixdown_idx */
      FDKwriteBits(hBs, pseudoSurroundEnable&0x1, 1);           /* pseudo_surround_enable */
  }
  else {
      FDKwriteBits(hBs, 0, 1);                                  /* Matrix mixdown not present */
  }

  for(i=0; i<config->num_front_channel_elements; i++) {
      UCHAR isCpe = (*pEl_list++==ID_CPE) ? 1 : 0;
      UCHAR tag   = (isCpe) ? cpeCnt++ : sceCnt++;
      FDKwriteBits(hBs, isCpe, 1);                              /* Front channel Elements is CPE? */
      FDKwriteBits(hBs, tag, 4);                                /* Front channel Instance Tag.*/
  }
  for(i=0; i<config->num_side_channel_elements; i++) {
      UCHAR isCpe = (*pEl_list++==ID_CPE) ? 1 : 0;
      UCHAR tag   = (isCpe) ? cpeCnt++ : sceCnt++;
      FDKwriteBits(hBs, isCpe, 1);                              /* Front channel Elements is CPE? */
      FDKwriteBits(hBs, tag, 4);                                /* Front channel Instance Tag.*/
  }
  for(i=0; i<config->num_back_channel_elements; i++) {
      UCHAR isCpe = (*pEl_list++==ID_CPE) ? 1 : 0;
      UCHAR tag   = (isCpe) ? cpeCnt++ : sceCnt++;
      FDKwriteBits(hBs, isCpe, 1);                              /* Front channel Elements is CPE? */
      FDKwriteBits(hBs, tag, 4);                                /* Front channel Instance Tag.*/
  }
  for(i=0; i<config->num_lfe_channel_elements; i++) {
      FDKwriteBits(hBs, lfeCnt++, 4);                           /* LFE channel Instance Tag. */
  }

  /* - num_valid_cc_elements always 0.
     - num_assoc_data_elements always 0. */

  /* Byte alignment: relative to alignAnchor
       ADTS: align with respect to the first bit of the raw_data_block()
       ADIF: align with respect to the first bit of the header
       LATM: align with respect to the first bit of the ASC */
  FDKbyteAlign(hBs, alignAnchor);                               /* Alignment */

  FDKwriteBits(hBs, 0 ,8);                                      /* Do no write any comment. */

  /* - comment_field_bytes always 0. */

  return 0;
}
Пример #6
0
/**
 * \brief adjust bit stream position and the end of an access unit.
 * \param hTp transport decoder handle.
 * \return error code.
 */
static
TRANSPORTDEC_ERROR transportDec_AdjustEndOfAccessUnit(HANDLE_TRANSPORTDEC hTp)
{
  HANDLE_FDK_BITSTREAM hBs = &hTp->bitStream[0];
  TRANSPORTDEC_ERROR err = TRANSPORTDEC_OK;

  switch (hTp->transportFmt) {
    case TT_MP4_LOAS:
    case TT_MP4_LATM_MCP0:
    case TT_MP4_LATM_MCP1:
      if ( hTp->numberOfRawDataBlocks == 0 )
      {
        /* Do byte align at the end of AudioMuxElement. */
        FDKbyteAlign(hBs, hTp->globalFramePos);

        /* Check global frame length */
        if (hTp->transportFmt == TT_MP4_LOAS && hTp->parser.latm.m_audioMuxLengthBytes > 0)
        {
          int loasOffset;

          loasOffset = (hTp->parser.latm.m_audioMuxLengthBytes*8 + FDKgetValidBits(hBs)) - hTp->globalFramePos;
          if (loasOffset != 0) {
            FDKpushBiDirectional(hBs, loasOffset);
            /* For ELD and other payloads there is an unknown amount of padding, so ignore unread bits, but
               throw an error only if too many bits where read. */
            if (loasOffset < 0) {
              err = TRANSPORTDEC_PARSE_ERROR;
            }
          }
        }
      }
      break;

    case TT_MP4_ADTS:
      if (hTp->parser.adts.bs.protection_absent == 0)
      {
        int offset;

        /* Calculate offset to end of AU */
        offset  = hTp->parser.adts.rawDataBlockDist[hTp->parser.adts.bs.num_raw_blocks-hTp->numberOfRawDataBlocks]<<3;
        /* CAUTION: The PCE (if available) is declared to be a part of the header! */
        offset -= hTp->accessUnitAnchor[0] - FDKgetValidBits(hBs) + 16 + hTp->parser.adts.bs.num_pce_bits;
        FDKpushBiDirectional(hBs, offset);
      }
      if (hTp->parser.adts.bs.num_raw_blocks > 0 && hTp->parser.adts.bs.protection_absent == 0) {
        /* Note this CRC read currently happens twice because of transportDec_CrcCheck() */
        hTp->parser.adts.crcReadValue = FDKreadBits(hBs, 16);
      }
      if ( hTp->numberOfRawDataBlocks == 0 )
      {
        /* Check global frame length */
        if (hTp->parser.adts.bs.protection_absent == 0)
        {
          int offset;

          offset = (hTp->parser.adts.bs.frame_length*8 - ADTS_SYNCLENGTH + FDKgetValidBits(hBs)) - hTp->globalFramePos;
          if (offset != 0) {
            FDKpushBiDirectional(hBs, offset);
          }
        }
      }
      break;

    default:
      break;
  }

  return err;
}