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); }
/* * 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); }
/** * \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; }
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; }
/** * \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; }