/*! \brief crc interface \return 1: CRC OK, 0: CRC check failure */ int SbrCrcCheck(HANDLE_FDK_BITSTREAM hBs, /*!< handle to bit-buffer */ LONG NrBits) /*!< max. CRC length */ { int crcResult = 1; ULONG NrCrcBits; ULONG crcCheckResult; LONG NrBitsAvailable; ULONG crcCheckSum; crcCheckSum = FDKreadBits(hBs, 10); NrBitsAvailable = FDKgetValidBits(hBs); if (NrBitsAvailable <= 0) { return 0; } NrCrcBits = fixMin((INT)NrBits, (INT)NrBitsAvailable); crcCheckResult = getCrc(hBs, NrCrcBits); FDKpushBack(hBs, (NrBitsAvailable - FDKgetValidBits(hBs))); if (crcCheckResult != crcCheckSum) { crcResult = 0; } return (crcResult); }
/*--------------------------------------------------------------------------------------------- description: This function returns a bit from the bitstream according to read direction. It is called very often, therefore it makes sense to inline it (runtime). ----------------------------------------------------------------------------------------------- input: - handle to FDK bitstream - reference value marking start of bitfield - pLeftStartOfSegment - pRightStartOfSegment - readDirection ----------------------------------------------------------------------------------------------- return: - bit from bitstream -------------------------------------------------------------------------------------------- */ UINT HcrGetABitFromBitstream(HANDLE_FDK_BITSTREAM bs, const INT bsAnchor, INT *pLeftStartOfSegment, INT *pRightStartOfSegment, UCHAR readDirection) { UINT bit; INT readBitOffset; if (readDirection == FROM_LEFT_TO_RIGHT) { readBitOffset = (INT)FDKgetValidBits(bs) - bsAnchor + *pLeftStartOfSegment; if (readBitOffset) { FDKpushBiDirectional(bs, readBitOffset); } bit = FDKreadBits(bs, 1); *pLeftStartOfSegment += 1; } else { readBitOffset = (INT)FDKgetValidBits(bs) - bsAnchor + *pRightStartOfSegment; if (readBitOffset) { FDKpushBiDirectional(bs, readBitOffset); } /* to be replaced with a brother function of FDKreadBits() */ bit = FDKreadBits(bs, 1); FDKpushBack(bs, 2); *pRightStartOfSegment -= 1; } return (bit); }
/***************************************************************************** functionname: FDKaacEnc_encodeSpectralData description: encode spectral data returns: the number of written bits input: output: *****************************************************************************/ static INT FDKaacEnc_encodeSpectralData(INT *sfbOffset, SECTION_DATA *sectionData, SHORT *quantSpectrum, HANDLE_FDK_BITSTREAM hBitStream) { INT i,sfb; INT dbgVal = FDKgetValidBits(hBitStream); for(i=0;i<sectionData->noOfSections;i++) { if(sectionData->huffsection[i].codeBook != CODE_BOOK_PNS_NO) { /* huffencode spectral data for this huffsection */ INT tmp = sectionData->huffsection[i].sfbStart+sectionData->huffsection[i].sfbCnt; for(sfb=sectionData->huffsection[i].sfbStart; sfb<tmp; sfb++) { FDKaacEnc_codeValues(quantSpectrum+sfbOffset[sfb], sfbOffset[sfb+1]-sfbOffset[sfb], sectionData->huffsection[i].codeBook, hBitStream); } } } return(FDKgetValidBits(hBitStream)-dbgVal); }
int dabWrite_EncodeHeader(HANDLE_DAB hDab, HANDLE_FDK_BITSTREAM hBitStream, int buffer_fullness, int frame_length) { INT crcIndex = 0; FDK_ASSERT(((frame_length+hDab->headerBits)/8)<0x2000); /*13 bit*/ FDK_ASSERT(buffer_fullness<0x800); /* 11 bit */ FDKcrcReset(&hDab->crcInfo); // fprintf(stderr, "dabWrite_EncodeHeader() hDab->currentBlock=%d, frame_length=%d, buffer_fullness=%d\n", // hDab->currentBlock, frame_length, buffer_fullness); // if (hDab->currentBlock == 0) { // //hDab->subFrameStartPrev=dabWrite_GetHeaderBits(hDab); // fprintf(stderr, "header bits[%d] [%d]\n", hDab->subFrameStartPrev, hDab->subFrameStartPrev >> 3); // FDKresetBitbuffer(hBitStream, BS_WRITER); // } //hDab->subFrameStartBit = FDKgetValidBits(hBitStream); // fprintf(stderr, "dabWrite_EncodeHeader() hDab->subFrameStartBit=%d [%d]\n", hDab->subFrameStartBit, hDab->subFrameStartBit >> 3); //hDab->subFrameStartBit = FDKgetValidBits(hBitStream); /* Skip new header if this is raw data block 1..n */ if (hDab->currentBlock == 0) { FDKresetBitbuffer(hBitStream, BS_WRITER); // fprintf(stderr, "dabWrite_EncodeHeader() after FDKresetBitbuffer=%d [%d]\n", FDKgetValidBits(hBitStream), FDKgetValidBits(hBitStream) >> 3); /* fixed header */ FDKwriteBits(hBitStream, 0, 16); //header_firecode FDKwriteBits(hBitStream, 0, 1); //rfa FDKwriteBits(hBitStream, hDab->dac_rate, 1); FDKwriteBits(hBitStream, hDab->sbr_flag, 1); FDKwriteBits(hBitStream, hDab->aac_channel_mode, 1); FDKwriteBits(hBitStream, hDab->ps_flag, 1); FDKwriteBits(hBitStream, hDab->mpeg_surround_config, 3); /* variable header */ int i; for(i=0; i<hDab->num_raw_blocks; i++) FDKwriteBits(hBitStream, 0, 12); /* padding */ if (hDab->dac_rate == 0 || hDab->sbr_flag == 0) { FDKwriteBits(hBitStream, 0, 4); } } /* End of DAB header */ hDab->subFrameStartBit = FDKgetValidBits(hBitStream); FDK_ASSERT(FDKgetValidBits(hBitStream) % 8 == 0); //only aligned header // fprintf(stderr, "dabWrite_EncodeHeader() FDKgetValidBits(hBitStream)=%d [%d]\n", FDKgetValidBits(hBitStream), FDKgetValidBits(hBitStream) >> 3); return 0; }
static TRANSPORTDEC_ERROR AudioSpecificConfig_ExtensionParse(CSAudioSpecificConfig *self, HANDLE_FDK_BITSTREAM bs, CSTpCallBacks *cb) { TP_ASC_EXTENSION_ID lastAscExt, ascExtId = ASCEXT_UNKOWN; INT bitsAvailable = (INT)FDKgetValidBits(bs); while (bitsAvailable >= 11) { lastAscExt = ascExtId; ascExtId = (TP_ASC_EXTENSION_ID)FDKreadBits(bs, 11); bitsAvailable -= 11; switch (ascExtId) { case ASCEXT_SBR: /* 0x2b7 */ if ( (self->m_extensionAudioObjectType != AOT_SBR) && (bitsAvailable >= 5) ) { self->m_extensionAudioObjectType = getAOT(bs); if ( (self->m_extensionAudioObjectType == AOT_SBR) || (self->m_extensionAudioObjectType == AOT_ER_BSAC) ) { /* Get SBR extension configuration */ self->m_sbrPresentFlag = FDKreadBits(bs, 1); bitsAvailable -= 1; if ( self->m_sbrPresentFlag == 1 ) { self->m_extensionSamplingFrequency = getSampleRate(bs, &self->m_extensionSamplingFrequencyIndex, 4); if ((INT)self->m_extensionSamplingFrequency <= 0) { return TRANSPORTDEC_PARSE_ERROR; } } if ( self->m_extensionAudioObjectType == AOT_ER_BSAC ) { self->m_extensionChannelConfiguration = FDKreadBits(bs, 4); bitsAvailable -= 4; } } /* Update counter because of variable length fields (AOT and sampling rate) */ bitsAvailable = (INT)FDKgetValidBits(bs); } break; case ASCEXT_PS: /* 0x548 */ if ( (lastAscExt == ASCEXT_SBR) && (self->m_extensionAudioObjectType == AOT_SBR) && (bitsAvailable > 0) ) { /* Get PS extension configuration */ self->m_psPresentFlag = FDKreadBits(bs, 1); bitsAvailable -= 1; } break; default: /* Just ignore anything. */ return TRANSPORTDEC_OK; } } return TRANSPORTDEC_OK; }
/* * 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); }
INT transportDec_GetAuBitsRemaining( const HANDLE_TRANSPORTDEC hTp, const UINT layer ) { INT bits; if (hTp->accessUnitAnchor[layer] > 0 && hTp->auLength[layer] > 0) { bits = hTp->auLength[layer] - (hTp->accessUnitAnchor[layer] - FDKgetValidBits(&hTp->bitStream[layer])); } else { bits = FDKgetValidBits(&hTp->bitStream[layer]); } return bits; }
/***************************************************************************** functionname: FDKaacEnc_encodeSectionData description: encode section data (common Huffman codebooks for adjacent SFB's) returns: none input: output: *****************************************************************************/ static INT FDKaacEnc_encodeSectionData(SECTION_DATA *sectionData, HANDLE_FDK_BITSTREAM hBitStream, UINT useVCB11) { if (hBitStream != NULL) { INT sectEscapeVal=0,sectLenBits=0; INT sectLen; INT i; INT dbgVal=FDKgetValidBits(hBitStream); INT sectCbBits = 4; switch(sectionData->blockType) { case LONG_WINDOW: case START_WINDOW: case STOP_WINDOW: sectEscapeVal = SECT_ESC_VAL_LONG; sectLenBits = SECT_BITS_LONG; break; case SHORT_WINDOW: sectEscapeVal = SECT_ESC_VAL_SHORT; sectLenBits = SECT_BITS_SHORT; break; } for(i=0;i<sectionData->noOfSections;i++) { INT codeBook = sectionData->huffsection[i].codeBook; FDKwriteBits(hBitStream,codeBook,sectCbBits); { sectLen = sectionData->huffsection[i].sfbCnt; while(sectLen >= sectEscapeVal) { FDKwriteBits(hBitStream,sectEscapeVal,sectLenBits); sectLen-=sectEscapeVal; } FDKwriteBits(hBitStream,sectLen,sectLenBits); } } return(FDKgetValidBits(hBitStream)-dbgVal); } return (0); }
INT FDKsbrEnc_CountSbrChannelPairElement( HANDLE_SBR_HEADER_DATA sbrHeaderData, HANDLE_PARAMETRIC_STEREO hParametricStereo, HANDLE_SBR_BITSTREAM_DATA sbrBitstreamData, HANDLE_SBR_ENV_DATA sbrEnvDataLeft, HANDLE_SBR_ENV_DATA sbrEnvDataRight, HANDLE_COMMON_DATA cmonData, UINT sbrSyntaxFlags) { INT payloadBits; INT bitPos = FDKgetValidBits(&cmonData->sbrBitbuf); payloadBits = FDKsbrEnc_WriteEnvChannelPairElement( sbrHeaderData, hParametricStereo, sbrBitstreamData, sbrEnvDataLeft, sbrEnvDataRight, cmonData, sbrSyntaxFlags); FDKpushBack(&cmonData->sbrBitbuf, (FDKgetValidBits(&cmonData->sbrBitbuf) - bitPos)); return payloadBits; }
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); }
int adifWrite_EncodeHeader(ADIF_INFO *adif, HANDLE_FDK_BITSTREAM hBs, INT adif_buffer_fullness) { /* ADIF/PCE/ADTS definitions */ const char adifId[5]="ADIF"; const int copyRightIdPresent=0; const int originalCopy=0; const int home=0; int i; INT sampleRate = adif->samplingRate; INT totalBitRate = adif->bitRate; if (adif->headerWritten) return 0; /* Align inside PCE with respect to the first bit of the header */ UINT alignAnchor = FDKgetValidBits(hBs); /* Signal variable bitrate if buffer fullnes exceeds 20 bit */ adif->bVariableRate = ( adif_buffer_fullness >= (INT)(0x1<<20) ) ? 1 : 0; FDKwriteBits(hBs, adifId[0],8); FDKwriteBits(hBs, adifId[1],8); FDKwriteBits(hBs, adifId[2],8); FDKwriteBits(hBs, adifId[3],8); FDKwriteBits(hBs, copyRightIdPresent ? 1:0,1); if(copyRightIdPresent) { for(i=0;i<72;i++) { FDKwriteBits(hBs,0,1); } } FDKwriteBits(hBs, originalCopy ? 1:0,1); FDKwriteBits(hBs, home ? 1:0,1); FDKwriteBits(hBs, adif->bVariableRate?1:0, 1); FDKwriteBits(hBs, totalBitRate,23); /* we write only one PCE at the moment */ FDKwriteBits(hBs, 0, 4); if(!adif->bVariableRate) { FDKwriteBits(hBs, adif_buffer_fullness, 20); } /* Write PCE */ transportEnc_writePCE(hBs, adif->cm, sampleRate, adif->instanceTag, adif->profile, 0, 0, alignAnchor); return 0; }
TRANSPORTENC_ERROR transportEnc_GetFrame(HANDLE_TRANSPORTENC hTpEnc, int *nbytes) { HANDLE_FDK_BITSTREAM hBs = &hTpEnc->bitStream; switch (hTpEnc->transportFmt) { case TT_MP4_LATM_MCP0: case TT_MP4_LATM_MCP1: case TT_MP4_LOAS: *nbytes = hTpEnc->bsBufferSize; transportEnc_LatmGetFrame(&hTpEnc->writer.latm, hBs, nbytes); break; case TT_MP4_ADTS: if (hTpEnc->writer.adts.currentBlock >= hTpEnc->writer.adts.num_raw_blocks+1) { *nbytes = (FDKgetValidBits(hBs) + 7)>>3; hTpEnc->writer.adts.currentBlock = 0; } else {
static INT getSampleRate(HANDLE_FDK_BITSTREAM bs, UCHAR *index, int nBits) { INT sampleRate; int idx; idx = FDKreadBits(bs, nBits); if( idx == (1<<nBits)-1 ) { if(FDKgetValidBits(bs) < 24) { return 0; } sampleRate = FDKreadBits(bs,24); } else { sampleRate = SamplingRateTable[idx]; } *index = idx; return sampleRate; }
TRANSPORTDEC_ERROR transportDec_CrcCheck(HANDLE_TRANSPORTDEC pTp) { switch (pTp->transportFmt) { case TT_MP4_ADTS: if ( (pTp->parser.adts.bs.num_raw_blocks > 0) && (pTp->parser.adts.bs.protection_absent == 0) ) { HANDLE_FDK_BITSTREAM hBs = &pTp->bitStream[0]; int bitDiff; /* Calculate possible offset to CRC value. */ bitDiff = pTp->parser.adts.rawDataBlockDist[pTp->parser.adts.bs.num_raw_blocks-pTp->numberOfRawDataBlocks]<<3; bitDiff -= pTp->globalFramePos - FDKgetValidBits(hBs) + 16; FDKpushBiDirectional(hBs, bitDiff); pTp->parser.adts.crcReadValue = FDKreadBits(hBs, 16); } return adtsRead_CrcCheck(&pTp->parser.adts); default: return TRANSPORTDEC_OK; } }
/** * \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; }
TRANSPORTDEC_ERROR DrmRawSdcAudioConfig_Parse( CSAudioSpecificConfig *self, HANDLE_FDK_BITSTREAM bs ) { TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; AudioSpecificConfig_Init(self); if ((INT)FDKgetValidBits(bs) < 20) { ErrorStatus = TRANSPORTDEC_PARSE_ERROR; goto bail; } else { /* DRM - Audio information data entity - type 9 - Short Id 2 bits - Stream Id 2 bits - audio coding 2 bits - SBR flag 1 bit - audio mode 2 bits - audio sampling rate 3 bits - text flag 1 bit - enhancement flag 1 bit - coder field 5 bits - rfa 1 bit */ int audioCoding, audioMode, cSamplingFreq, coderField, sfIdx, sbrFlag; /* Read the SDC field */ FDKreadBits(bs,4); /* Short and Stream Id */ audioCoding = FDKreadBits(bs, 2); sbrFlag = FDKreadBits(bs, 1); audioMode = FDKreadBits(bs, 2); cSamplingFreq = FDKreadBits(bs, 3); /* audio sampling rate */ FDKreadBits(bs, 2); /* Text and enhancement flag */ coderField = FDKreadBits(bs, 5); FDKreadBits(bs, 1); /* rfa */ /* Evaluate configuration and fill the ASC */ switch (cSamplingFreq) { case 0: /* 8 kHz */ sfIdx = 11; break; case 1: /* 12 kHz */ sfIdx = 9; break; case 2: /* 16 kHz */ sfIdx = 8; break; case 3: /* 24 kHz */ sfIdx = 6; break; case 5: /* 48 kHz */ sfIdx = 3; break; case 4: /* reserved */ case 6: /* reserved */ case 7: /* reserved */ default: ErrorStatus = TRANSPORTDEC_PARSE_ERROR; goto bail; } self->m_samplingFrequencyIndex = sfIdx; self->m_samplingFrequency = SamplingRateTable[sfIdx]; if ( sbrFlag ) { UINT i; int tmp = -1; self->m_sbrPresentFlag = 1; self->m_extensionAudioObjectType = AOT_SBR; self->m_extensionSamplingFrequency = self->m_samplingFrequency << 1; for (i=0; i<(sizeof(SamplingRateTable)/sizeof(SamplingRateTable[0])); i++){ if (SamplingRateTable[i] == self->m_extensionSamplingFrequency){ tmp = i; break; } } self->m_extensionSamplingFrequencyIndex = tmp; } switch (audioCoding) { case 0: /* AAC */ self->m_aot = AOT_DRM_AAC ; /* Set pseudo AOT for Drm AAC */ switch (audioMode) { case 1: /* parametric stereo */ self->m_psPresentFlag = 1; case 0: /* mono */ self->m_channelConfiguration = 1; break; case 2: /* stereo */ self->m_channelConfiguration = 2; break; default: ErrorStatus = TRANSPORTDEC_PARSE_ERROR; goto bail; } self->m_vcb11Flag = 1; self->m_hcrFlag = 1; self->m_samplesPerFrame = 960; self->m_epConfig = 1; break; case 1: /* CELP */ self->m_aot = AOT_ER_CELP; self->m_channelConfiguration = 1; break; case 2: /* HVXC */ self->m_aot = AOT_ER_HVXC; self->m_channelConfiguration = 1; break; case 3: /* reserved */ default: ErrorStatus = TRANSPORTDEC_PARSE_ERROR; self->m_aot = AOT_NONE; break; } if (self->m_psPresentFlag && !self->m_sbrPresentFlag) { ErrorStatus = TRANSPORTDEC_PARSE_ERROR; goto bail; } } bail: return (ErrorStatus); }
void dabWrite_EndRawDataBlock(HANDLE_DAB hDab, HANDLE_FDK_BITSTREAM hBs, int *pBits) { FDK_BITSTREAM bsWriter; INT crcIndex = 0; USHORT crcData; INT writeBits=0; INT writeBitsNonLastBlock=0; INT writeBitsLastBlock=0; #if 1 if (hDab->currentBlock == hDab->num_raw_blocks) { //calculate byte-alignment before writing ID_FIL if((FDKgetValidBits(hBs)+3) % 8){ writeBits = 8 - ((FDKgetValidBits(hBs)+3) % 8); } INT offset_end = hDab->subchannels_num*110*8 - 2*8 - 3; writeBitsLastBlock = offset_end - FDKgetValidBits(hBs); dabWrite_FillRawDataBlock(hBs, writeBitsLastBlock); FDKsyncCache(hBs); //fprintf(stderr, "FIL-element written=%d\n", writeBitsLastBlock); writeBitsLastBlock=writeBits; } #endif FDKwriteBits(hBs, 7, 3); //finalize AU: ID_END FDKsyncCache(hBs); //byte-align (if ID_FIL doesn't align it). if(FDKgetValidBits(hBs) % 8){ writeBits = 8 - (FDKgetValidBits(hBs) % 8); FDKwriteBits(hBs, 0x00, writeBits); FDKsyncCache(hBs); } //fake-written bits alignment for last AU if (hDab->currentBlock == hDab->num_raw_blocks) writeBits=writeBitsLastBlock; INT frameLen = (FDKgetValidBits(hBs) - hDab->subFrameStartBit) >> 3; //fprintf(stderr, "frame=%d, offset writeBits=%d\n", frameLen, writeBits); FDK_ASSERT(FDKgetValidBits(hBs) % 8 == 0); //only aligned au's FDK_ASSERT(hDab->subchannels_num*110*8 >= FDKgetValidBits(hBs)+2*8); //don't overlap superframe FDKinitBitStream(&bsWriter, hBs->hBitBuf.Buffer, hBs->hBitBuf.bufSize, 0, BS_WRITER); FDKpushFor(&bsWriter, hDab->subFrameStartBit); FDKcrcReset(&hDab->crcInfo); hDab->crcIndex = FDKcrcStartReg(&hDab->crcInfo, &bsWriter, 0); #if 0 if (hDab->currentBlock == hDab->num_raw_blocks) { INT offset_size = hDab->subchannels_num*110*8 - 2*8 - FDKgetValidBits(hBs); //fprintf(stderr, "offset_size=%d\n", offset_size >> 3); FDKpushFor(hBs, offset_size); } #endif FDKpushFor(&bsWriter, FDKgetValidBits(hBs) - hDab->subFrameStartBit); FDKcrcEndReg(&hDab->crcInfo, &bsWriter, hDab->crcIndex); crcData = FDKcrcGetCRC(&hDab->crcInfo); //fprintf(stderr, "crcData = %04x\n", crcData); /* Write inverted CRC of current raw data block */ FDKwriteBits(hBs, crcData ^ 0xffff, 16); FDKsyncCache(hBs); /* Write distance to current data block */ if(hDab->currentBlock) { FDKinitBitStream(&bsWriter, hBs->hBitBuf.Buffer, hBs->hBitBuf.bufSize, 0, BS_WRITER); FDKpushFor(&bsWriter, 24 + (hDab->currentBlock-1)*12); //fprintf(stderr, "FDKwriteBits() = %d\n", hDab->subFrameStartBit>>3); FDKwriteBits(&bsWriter, (hDab->subFrameStartBit>>3), 12); FDKsyncCache(&bsWriter); }
/** * \brief Synchronize to stream and estimate the amount of missing access units due * to a current synchronization error in case of constant average bit rate. */ static TRANSPORTDEC_ERROR transportDec_readStream ( HANDLE_TRANSPORTDEC hTp, const UINT layer ) { TRANSPORTDEC_ERROR error = TRANSPORTDEC_OK; HANDLE_FDK_BITSTREAM hBs = &hTp->bitStream[layer]; INT nAU = -1; INT headerBits; INT bitDistance, bfDelta; /* Obtain distance to next synch word */ bitDistance = FDKgetValidBits(hBs); error = synchronization(hTp, &headerBits); bitDistance -= FDKgetValidBits(hBs); FDK_ASSERT(bitDistance >= 0); if (error == TRANSPORTDEC_SYNC_ERROR || (hTp->flags & TPDEC_LOST_FRAMES_PENDING)) { /* Check if estimating lost access units is feasible. */ if (hTp->avgBitRate > 0 && hTp->asc[0].m_samplesPerFrame > 0 && hTp->asc[0].m_samplingFrequency > 0) { if (error == TRANSPORTDEC_OK) { int aj; aj = transportDec_GetBufferFullness(hTp); if (aj > 0) { bfDelta = aj; } else { bfDelta = 0; } /* sync was ok: last of a series of bad access units. */ hTp->flags &= ~TPDEC_LOST_FRAMES_PENDING; /* Add up bitDistance until end of the current frame. Later we substract this frame from the grand total, since this current successfully synchronized frame should not be skipped of course; but it must be accounted into the bufferfulness math. */ bitDistance += hTp->auLength[0]; } else { if ( !(hTp->flags & TPDEC_LOST_FRAMES_PENDING) ) { /* sync not ok: one of many bad access units. */ hTp->flags |= TPDEC_LOST_FRAMES_PENDING; bfDelta = - (INT)hTp->lastValidBufferFullness; } else { bfDelta = 0; } } { int num, denom; /* Obtain estimate of number of lost frames */ num = hTp->asc[0].m_samplingFrequency * (bfDelta + bitDistance) + hTp->remainder; denom = hTp->avgBitRate * hTp->asc[0].m_samplesPerFrame; if (num > 0) { nAU = num / denom; hTp->remainder = num % denom; } else { hTp->remainder = num; } if (error == TRANSPORTDEC_OK) { /* Final adjustment of remainder, taken -1 into account because current frame should not be skipped, thus substract -1 or do nothing instead of +1-1 accordingly. */ if ( (denom - hTp->remainder) >= hTp->remainder ) { nAU--; } if (nAU < 0) { /* There was one frame too much concealed, so unfortunately we will have to skip one good frame. */ transportDec_EndAccessUnit(hTp); error = synchronization(hTp, &headerBits); nAU = -1; #ifdef DEBUG FDKprintf("ERROR: Bufferfullness accounting failed. remainder=%d, nAU=%d\n", hTp->remainder, nAU); #endif } hTp->remainder = 0; /* Enforce last missed frames to be concealed. */ if (nAU > 0) { FDKpushBack(hBs, headerBits); } } } } } /* Be sure that lost frames are handled correctly. This is necessary due to some sync error sequences where later it turns out that there is not enough data, but the bits upto the sync word are discarded, thus causing a value of nAU > 0 */ if (nAU > 0) { error = TRANSPORTDEC_SYNC_ERROR; } hTp->missingAccessUnits = nAU; return error; }
int transportEnc_writeASC ( HANDLE_FDK_BITSTREAM asc, CODER_CONFIG *config, CSTpCallBacks *cb ) { UINT extFlag = 0; int err; int epConfig = 0; /* Required for the PCE. */ UINT alignAnchor = FDKgetValidBits(asc); /* Extension Flag: Shall be 1 for aot = 17,19,20,21,22,23,39 */ switch (config->aot) { case AOT_ER_AAC_LC: case AOT_ER_AAC_LTP: case AOT_ER_AAC_SCAL: case AOT_ER_TWIN_VQ: case AOT_ER_BSAC: case AOT_ER_AAC_LD: case AOT_ER_AAC_ELD: case AOT_USAC: extFlag = 1; break; default: break; } if (config->extAOT == AOT_SBR || config->extAOT == AOT_PS) writeAot(asc, config->extAOT); else writeAot(asc, config->aot); { writeSampleRate(asc, config->samplingRate); } /* Try to guess a reasonable channel mode if not given */ if (config->channelMode == MODE_INVALID) { config->channelMode = transportEnc_GetChannelMode(config->noChannels); if (config->channelMode == MODE_INVALID) return -1; } FDKwriteBits( asc, getChannelConfig(config->channelMode), 4 ); if (config->extAOT == AOT_SBR || config->extAOT == AOT_PS) { writeSampleRate(asc, config->extSamplingRate); writeAot(asc, config->aot); } switch (config->aot) { #ifdef TP_GA_ENABLE case AOT_AAC_MAIN: case AOT_AAC_LC: case AOT_AAC_SSR: case AOT_AAC_LTP: case AOT_AAC_SCAL: case AOT_TWIN_VQ: case AOT_ER_AAC_LC: case AOT_ER_AAC_LTP: case AOT_ER_AAC_SCAL: case AOT_ER_TWIN_VQ: case AOT_ER_BSAC: case AOT_ER_AAC_LD: err = transportEnc_writeGASpecificConfig(asc, config, extFlag, alignAnchor); if (err) return err; break; #endif /* TP_GA_ENABLE */ #ifdef TP_ELD_ENABLE case AOT_ER_AAC_ELD: err = transportEnc_writeELDSpecificConfig(asc, config, epConfig, cb); if (err) return err; break; #endif /* TP_ELD_ENABLE */ default: return -1; } switch (config->aot) { case AOT_ER_AAC_LC: case AOT_ER_AAC_LTP: case AOT_ER_AAC_SCAL: case AOT_ER_TWIN_VQ: case AOT_ER_BSAC: case AOT_ER_AAC_LD: case AOT_ER_CELP: case AOT_ER_HVXC: case AOT_ER_HILN: case AOT_ER_PARA: case AOT_ER_AAC_ELD: FDKwriteBits( asc, 0, 2 ); /* epconfig 0 */ break; default: break; } /* Make sure all bits are sync'ed */ FDKsyncCache( asc ); return 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; }
void FDKsbrEnc_AssembleSbrBitstream( HANDLE_COMMON_DATA hCmonData, HANDLE_FDK_CRCINFO hCrcInfo, INT crcRegion, UINT sbrSyntaxFlags) { USHORT crcReg = SBR_CRCINIT; INT numCrcBits,i; /* check if SBR is present */ if ( hCmonData==NULL ) return; hCmonData->sbrFillBits = 0; /* Fill bits are written only for GA streams */ if ( sbrSyntaxFlags & SBR_SYNTAX_DRM_CRC ) { /* * Calculate and write DRM CRC */ FDKcrcEndReg( hCrcInfo, &hCmonData->sbrBitbuf, crcRegion ); FDKwriteBits( &hCmonData->tmpWriteBitbuf, FDKcrcGetCRC(hCrcInfo)^0xFF, SI_SBR_DRM_CRC_BITS ); } else { if ( !(sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) ) { /* Do alignment here, because its defined as part of the sbr_extension_data */ int sbrLoad = hCmonData->sbrHdrBits + hCmonData->sbrDataBits; if ( sbrSyntaxFlags & SBR_SYNTAX_CRC ) { sbrLoad += SI_SBR_CRC_BITS; } sbrLoad += 4; /* Do byte Align with 4 bit offset. ISO/IEC 14496-3:2005(E) page 39. */ hCmonData->sbrFillBits = (8 - (sbrLoad % 8)) % 8; /* append fill bits */ FDKwriteBits(&hCmonData->sbrBitbuf, 0, hCmonData->sbrFillBits ); FDK_ASSERT(FDKgetValidBits(&hCmonData->sbrBitbuf) % 8 == 4); } /* calculate crc */ if ( sbrSyntaxFlags & SBR_SYNTAX_CRC ) { FDK_BITSTREAM tmpCRCBuf = hCmonData->sbrBitbuf; FDKresetBitbuffer( &tmpCRCBuf, BS_READER ); numCrcBits = hCmonData->sbrHdrBits + hCmonData->sbrDataBits + hCmonData->sbrFillBits; for(i=0;i<numCrcBits;i++){ INT bit; bit = FDKreadBits(&tmpCRCBuf,1); crcAdvance(SBR_CRC_POLY,SBR_CRC_MASK,&crcReg,bit,1); } crcReg &= (SBR_CRC_RANGE); /* * Write CRC data. */ FDKwriteBits (&hCmonData->tmpWriteBitbuf, crcReg, SI_SBR_CRC_BITS); } } FDKsyncCache(&hCmonData->tmpWriteBitbuf); }
static INT FDKaacEnc_encodeScaleFactorData(UINT *maxValueInSfb, SECTION_DATA *sectionData, INT *scalefac, HANDLE_FDK_BITSTREAM hBitStream, INT *RESTRICT noiseNrg, const INT *isScale, INT globalGain) { if (hBitStream != NULL) { INT i,j,lastValScf,deltaScf; INT deltaPns; INT lastValPns = 0; INT noisePCMFlag = TRUE; INT lastValIs; INT dbgVal = FDKgetValidBits(hBitStream); lastValScf=scalefac[sectionData->firstScf]; lastValPns = globalGain-scalefac[sectionData->firstScf]+globalGainOffset-4*LOG_NORM_PCM-noiseOffset; lastValIs = 0; for(i=0; i<sectionData->noOfSections; i++){ if (sectionData->huffsection[i].codeBook != CODE_BOOK_ZERO_NO) { if ((sectionData->huffsection[i].codeBook == CODE_BOOK_IS_OUT_OF_PHASE_NO) || (sectionData->huffsection[i].codeBook == CODE_BOOK_IS_IN_PHASE_NO)) { INT sfbStart = sectionData->huffsection[i].sfbStart; INT tmp = sfbStart + sectionData->huffsection[i].sfbCnt; for(j=sfbStart; j<tmp; j++) { INT deltaIs = isScale[j]-lastValIs;
TRANSPORTENC_ERROR transportEnc_WriteAccessUnit( HANDLE_TRANSPORTENC hTp, INT frameUsedBits, int bufferFullness, int ncc ) { TRANSPORTENC_ERROR err = TRANSPORTENC_OK; if (!hTp) { return TRANSPORTENC_INVALID_PARAMETER; } HANDLE_FDK_BITSTREAM hBs = &hTp->bitStream; /* In case of writing PCE in raw_data_block frameUsedBits must be adapted. */ if (hTp->pceFrameCounter>=hTp->config.headerPeriod) { frameUsedBits += transportEnc_GetPCEBits(hTp->config.channelMode, hTp->config.matrixMixdownA, 3); /* Consider 3 bits ID signalling in alignment */ } switch (hTp->transportFmt) { case TT_MP4_ADIF: FDKinitBitStream(&hTp->bitStream, hTp->bsBuffer, hTp->bsBufferSize, 0, BS_WRITER); adifWrite_EncodeHeader( &hTp->writer.adif, hBs, bufferFullness ); break; case TT_MP4_ADTS: bufferFullness /= ncc; /* Number of Considered Channels */ bufferFullness /= 32; bufferFullness = FDKmin(0x7FF, bufferFullness); /* Signal variable rate */ adtsWrite_EncodeHeader( &hTp->writer.adts, &hTp->bitStream, bufferFullness, frameUsedBits ); break; case TT_DABPLUS: bufferFullness /= ncc; /* Number of Considered Channels */ bufferFullness /= 32; bufferFullness = FDKmin(0x7FF, bufferFullness); /* Signal variable rate */ dabWrite_EncodeHeader( &hTp->writer.dab, &hTp->bitStream, bufferFullness, frameUsedBits ); break; case TT_MP4_LOAS: case TT_MP4_LATM_MCP0: case TT_MP4_LATM_MCP1: bufferFullness /= ncc; /* Number of Considered Channels */ bufferFullness /= 32; bufferFullness = FDKmin(0xFF, bufferFullness); /* Signal variable rate */ transportEnc_LatmWrite( &hTp->writer.latm, hBs, frameUsedBits, bufferFullness, &hTp->callbacks ); break; case TT_MP4_RAW: if (hTp->writer.raw.curSubFrame >= hTp->writer.raw.nSubFrames) { hTp->writer.raw.curSubFrame = 0; FDKinitBitStream(&hTp->bitStream, hTp->bsBuffer, hTp->bsBufferSize, 0, BS_WRITER); } hTp->writer.raw.prevBits = FDKgetValidBits(hBs); break; default: err = TRANSPORTENC_UNSUPPORTED_FORMAT; break; } /* Write PCE in raw_data_block if required */ if (hTp->pceFrameCounter>=hTp->config.headerPeriod) { INT crcIndex = 0; /* Align inside PCE with repsect to the first bit of the raw_data_block() */ UINT alignAnchor = FDKgetValidBits(&hTp->bitStream); /* Write PCE element ID bits */ FDKwriteBits(&hTp->bitStream, ID_PCE, 3); if ( (hTp->transportFmt==TT_MP4_ADTS) && !hTp->writer.adts.protection_absent) { crcIndex = adtsWrite_CrcStartReg(&hTp->writer.adts, &hTp->bitStream, 0); } /* Write PCE as first raw_data_block element */ transportEnc_writePCE(&hTp->bitStream, hTp->config.channelMode, hTp->config.samplingRate, 0, 1, hTp->config.matrixMixdownA, hTp->config.flags & CC_PSEUDO_SURROUND, alignAnchor); if ( (hTp->transportFmt==TT_MP4_ADTS) && !hTp->writer.adts.protection_absent) { adtsWrite_CrcEndReg(&hTp->writer.adts, &hTp->bitStream, crcIndex); } hTp->pceFrameCounter = 0; /* reset pce frame counter */ } if (hTp->pceFrameCounter!=-1) { hTp->pceFrameCounter++; /* Update pceFrameCounter only if PCE writing is active. */ } return err; }
SBR_ERROR sbrDecoder_Parse( HANDLE_SBRDECODER self, HANDLE_FDK_BITSTREAM hBs, int *count, int bsPayLen, int crcFlag, MP4_ELEMENT_ID prevElement, int elementIndex, int fGlobalIndependencyFlag ) { SBR_DECODER_ELEMENT *hSbrElement; HANDLE_SBR_HEADER_DATA hSbrHeader; HANDLE_SBR_CHANNEL *pSbrChannel; SBR_FRAME_DATA *hFrameDataLeft; SBR_FRAME_DATA *hFrameDataRight; SBR_ERROR errorStatus = SBRDEC_OK; SBR_SYNC_STATE initialSyncState; SBR_HEADER_STATUS headerStatus = HEADER_NOT_PRESENT; INT startPos; INT CRCLen = 0; int stereo; int fDoDecodeSbrData = 1; int lastSlot, lastHdrSlot = 0, thisHdrSlot; /* Remember start position of SBR element */ startPos = FDKgetValidBits(hBs); /* SBR sanity checks */ if ( self == NULL || self->pSbrElement[elementIndex] == NULL ) { errorStatus = SBRDEC_NOT_INITIALIZED; goto bail; } hSbrElement = self->pSbrElement[elementIndex]; lastSlot = (hSbrElement->useFrameSlot > 0) ? hSbrElement->useFrameSlot-1 : self->numDelayFrames; lastHdrSlot = hSbrElement->useHeaderSlot[lastSlot]; thisHdrSlot = getHeaderSlot( hSbrElement->useFrameSlot, hSbrElement->useHeaderSlot ); /* Get a free header slot not used by frames not processed yet. */ /* Assign the free slot to store a new header if there is one. */ hSbrHeader = &self->sbrHeader[elementIndex][thisHdrSlot]; pSbrChannel = hSbrElement->pSbrChannel; stereo = (hSbrElement->elementID == ID_CPE) ? 1 : 0; hFrameDataLeft = &self->pSbrElement[elementIndex]->pSbrChannel[0]->frameData[hSbrElement->useFrameSlot]; hFrameDataRight = &self->pSbrElement[elementIndex]->pSbrChannel[1]->frameData[hSbrElement->useFrameSlot]; initialSyncState = hSbrHeader->syncState; /* reset PS flag; will be set after PS was found */ self->flags &= ~SBRDEC_PS_DECODED; if (hSbrHeader->status & SBRDEC_HDR_STAT_UPDATE) { /* Got a new header from extern (e.g. from an ASC) */ headerStatus = HEADER_OK; hSbrHeader->status &= ~SBRDEC_HDR_STAT_UPDATE; } else if (thisHdrSlot != lastHdrSlot) { /* Copy the last header into this slot otherwise the header compare will trigger more HEADER_RESETs than needed. */ copySbrHeader( hSbrHeader, &self->sbrHeader[elementIndex][lastHdrSlot] ); } /* Check if bit stream data is valid and matches the element context */ if ( ((prevElement != ID_SCE) && (prevElement != ID_CPE)) || prevElement != hSbrElement->elementID) { /* In case of LFE we also land here, since there is no LFE SBR element (do upsampling only) */ fDoDecodeSbrData = 0; } if (fDoDecodeSbrData) { if ((INT)FDKgetValidBits(hBs) <= 0) { fDoDecodeSbrData = 0; } } /* SBR CRC-check */ if (fDoDecodeSbrData) { if (crcFlag == 1) { switch (self->coreCodec) { case AOT_ER_AAC_ELD: FDKpushFor (hBs, 10); /* check sbrcrc later: we don't know the payload length now */ break; default: CRCLen = bsPayLen - 10; /* change: 0 => i */ if (CRCLen < 0) { fDoDecodeSbrData = 0; } else { fDoDecodeSbrData = SbrCrcCheck (hBs, CRCLen); } break; } } } /* if (fDoDecodeSbrData) */ /* Read in the header data and issue a reset if change occured */ if (fDoDecodeSbrData) { int sbrHeaderPresent; { sbrHeaderPresent = FDKreadBit(hBs); } if ( sbrHeaderPresent ) { headerStatus = sbrGetHeaderData (hSbrHeader, hBs, self->flags, 1); } if (headerStatus == HEADER_RESET) { errorStatus = sbrDecoder_HeaderUpdate( self, hSbrHeader, headerStatus, pSbrChannel, hSbrElement->nChannels ); if (errorStatus == SBRDEC_OK) { hSbrHeader->syncState = SBR_HEADER; } else { hSbrHeader->syncState = SBR_NOT_INITIALIZED; } } if (errorStatus != SBRDEC_OK) { fDoDecodeSbrData = 0; } } /* if (fDoDecodeSbrData) */ /* Print debugging output only if state has changed */ /* read frame data */ if ((hSbrHeader->syncState >= SBR_HEADER) && fDoDecodeSbrData) { int sbrFrameOk; /* read the SBR element data */ if (stereo) { sbrFrameOk = sbrGetChannelPairElement(hSbrHeader, hFrameDataLeft, hFrameDataRight, hBs, self->flags, self->pSbrElement[elementIndex]->transposerSettings.overlap); } else { if (self->hParametricStereoDec != NULL) { /* update slot index for PS bitstream parsing */ self->hParametricStereoDec->bsLastSlot = self->hParametricStereoDec->bsReadSlot; self->hParametricStereoDec->bsReadSlot = hSbrElement->useFrameSlot; } sbrFrameOk = sbrGetSingleChannelElement(hSbrHeader, hFrameDataLeft, hBs, self->hParametricStereoDec, self->flags, self->pSbrElement[elementIndex]->transposerSettings.overlap); } if (!sbrFrameOk) { fDoDecodeSbrData = 0; } else { INT valBits; if (bsPayLen > 0) { valBits = bsPayLen - ((INT)startPos - (INT)FDKgetValidBits(hBs)); } else { valBits = (INT)FDKgetValidBits(hBs); } if ( crcFlag == 1 ) { switch (self->coreCodec) { case AOT_ER_AAC_ELD: { /* late crc check for eld */ INT payloadbits = (INT)startPos - (INT)FDKgetValidBits(hBs) - startPos; INT crcLen = payloadbits - 10; FDKpushBack(hBs, payloadbits); fDoDecodeSbrData = SbrCrcCheck (hBs, crcLen); FDKpushFor(hBs, crcLen); } break; default: break; } } /* sanity check of remaining bits */ if (valBits < 0) { fDoDecodeSbrData = 0; } else { switch (self->coreCodec) { case AOT_SBR: case AOT_PS: case AOT_AAC_LC: { /* This sanity check is only meaningful with General Audio bitstreams */ int alignBits = valBits & 0x7; if (valBits > alignBits) { fDoDecodeSbrData = 0; } } break; default: /* No sanity check available */ break; } } } } else { /* The returned bit count will not be the actual payload size since we did not parse the frame data. Return an error so that the caller can react respectively. */ errorStatus = SBRDEC_PARSE_ERROR; } if (!fDoDecodeSbrData) { /* Set error flag for this slot to trigger concealment */ self->pSbrElement[elementIndex]->frameErrorFlag[hSbrElement->useFrameSlot] = 1; errorStatus = SBRDEC_PARSE_ERROR; } else { /* Everything seems to be ok so clear the error flag */ self->pSbrElement[elementIndex]->frameErrorFlag[hSbrElement->useFrameSlot] = 0; } if (!stereo) { /* Turn coupling off explicitely to avoid access to absent right frame data that might occur with corrupt bitstreams. */ hFrameDataLeft->coupling = COUPLING_OFF; } bail: if (errorStatus == SBRDEC_OK) { if (headerStatus == HEADER_NOT_PRESENT) { /* Use the old header for this frame */ hSbrElement->useHeaderSlot[hSbrElement->useFrameSlot] = lastHdrSlot; } else { /* Use the new header for this frame */ hSbrElement->useHeaderSlot[hSbrElement->useFrameSlot] = thisHdrSlot; } /* Move frame pointer to the next slot which is up to be decoded/applied next */ hSbrElement->useFrameSlot = (hSbrElement->useFrameSlot+1) % (self->numDelayFrames+1); } *count -= startPos - FDKgetValidBits(hBs); return errorStatus; }
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; }
/*! \brief Reads parametric stereo data from bitstream \return ****************************************************************************/ unsigned int ReadPsData (HANDLE_PS_DEC h_ps_d, /*!< handle to struct PS_DEC */ HANDLE_FDK_BITSTREAM hBitBuf, /*!< handle to struct BIT_BUF */ int nBitsLeft /*!< max number of bits available */ ) { MPEG_PS_BS_DATA *pBsData; UCHAR gr, env; SCHAR dtFlag; INT startbits; Huffman CurrentTable; SCHAR bEnableHeader; if (!h_ps_d) return 0; pBsData = &h_ps_d->bsData[h_ps_d->bsReadSlot].mpeg; if (h_ps_d->bsReadSlot != h_ps_d->bsLastSlot) { /* Copy last header data */ FDKmemcpy(pBsData, &h_ps_d->bsData[h_ps_d->bsLastSlot].mpeg, sizeof(MPEG_PS_BS_DATA)); } startbits = (INT) FDKgetValidBits(hBitBuf); bEnableHeader = (SCHAR) FDKreadBits (hBitBuf, 1); /* Read header */ if (bEnableHeader) { pBsData->bPsHeaderValid = 1; pBsData->bEnableIid = (UCHAR) FDKreadBits (hBitBuf, 1); if (pBsData->bEnableIid) { pBsData->modeIid = (UCHAR) FDKreadBits (hBitBuf, 3); } pBsData->bEnableIcc = (UCHAR) FDKreadBits (hBitBuf, 1); if (pBsData->bEnableIcc) { pBsData->modeIcc = (UCHAR) FDKreadBits (hBitBuf, 3); } pBsData->bEnableExt = (UCHAR) FDKreadBits (hBitBuf, 1); } pBsData->bFrameClass = (UCHAR) FDKreadBits (hBitBuf, 1); if (pBsData->bFrameClass == 0) { /* FIX_BORDERS NoEnv=0,1,2,4 */ pBsData->noEnv = FDK_sbrDecoder_aFixNoEnvDecode[(UCHAR) FDKreadBits (hBitBuf, 2)]; /* all additional handling of env borders is now in DecodePs() */ } else { /* VAR_BORDERS NoEnv=1,2,3,4 */ pBsData->noEnv = 1+(UCHAR) FDKreadBits (hBitBuf, 2); for (env=1; env<pBsData->noEnv+1; env++) pBsData->aEnvStartStop[env] = ((UCHAR) FDKreadBits (hBitBuf, 5)) + 1; /* all additional handling of env borders is now in DecodePs() */ } /* verify that IID & ICC modes (quant grid, freq res) are supported */ if ((pBsData->modeIid > 5) || (pBsData->modeIcc > 5)) { /* no useful PS data could be read from bitstream */ h_ps_d->bPsDataAvail[h_ps_d->bsReadSlot] = ppt_none; /* discard all remaining bits */ nBitsLeft -= startbits - FDKgetValidBits(hBitBuf); while (nBitsLeft) { int i = nBitsLeft; if (i>8) { i = 8; } FDKreadBits (hBitBuf, i); nBitsLeft -= i; } return (startbits - FDKgetValidBits(hBitBuf)); } if (pBsData->modeIid > 2){ pBsData->freqResIid = pBsData->modeIid-3; pBsData->bFineIidQ = 1; } else{ pBsData->freqResIid = pBsData->modeIid; pBsData->bFineIidQ = 0; } if (pBsData->modeIcc > 2){ pBsData->freqResIcc = pBsData->modeIcc-3; } else{ pBsData->freqResIcc = pBsData->modeIcc; } /* Extract IID data */ if (pBsData->bEnableIid) { for (env=0; env<pBsData->noEnv; env++) { dtFlag = (SCHAR)FDKreadBits (hBitBuf, 1); if (!dtFlag) { if (pBsData->bFineIidQ) CurrentTable = (Huffman)&aBookPsIidFineFreqDecode; else CurrentTable = (Huffman)&aBookPsIidFreqDecode; } else { if (pBsData->bFineIidQ) CurrentTable = (Huffman)&aBookPsIidFineTimeDecode; else CurrentTable = (Huffman)&aBookPsIidTimeDecode; } for (gr = 0; gr < FDK_sbrDecoder_aNoIidBins[pBsData->freqResIid]; gr++) pBsData->aaIidIndex[env][gr] = decode_huff_cw(CurrentTable,hBitBuf,NULL); pBsData->abIidDtFlag[env] = dtFlag; } } /* Extract ICC data */ if (pBsData->bEnableIcc) { for (env=0; env<pBsData->noEnv; env++) { dtFlag = (SCHAR)FDKreadBits (hBitBuf, 1); if (!dtFlag) CurrentTable = (Huffman)&aBookPsIccFreqDecode; else CurrentTable = (Huffman)&aBookPsIccTimeDecode; for (gr = 0; gr < FDK_sbrDecoder_aNoIccBins[pBsData->freqResIcc]; gr++) pBsData->aaIccIndex[env][gr] = decode_huff_cw(CurrentTable,hBitBuf,NULL); pBsData->abIccDtFlag[env] = dtFlag; } } if (pBsData->bEnableExt) { /*! Decoders that support only the baseline version of the PS tool are allowed to ignore the IPD/OPD data, but according header data has to be parsed. ISO/IEC 14496-3 Subpart 8 Annex 4 */ int cnt = FDKreadBits(hBitBuf, PS_EXTENSION_SIZE_BITS); if (cnt == (1<<PS_EXTENSION_SIZE_BITS)-1) { cnt += FDKreadBits(hBitBuf, PS_EXTENSION_ESC_COUNT_BITS); } while (cnt--) FDKreadBits(hBitBuf, 8); } /* new PS data was read from bitstream */ h_ps_d->bPsDataAvail[h_ps_d->bsReadSlot] = ppt_mpeg; return (startbits - FDKgetValidBits(hBitBuf)); }
/* returns error code */ TRANSPORTDEC_ERROR transportDec_ReadAccessUnit( const HANDLE_TRANSPORTDEC hTp, const UINT layer ) { TRANSPORTDEC_ERROR err = TRANSPORTDEC_OK; HANDLE_FDK_BITSTREAM hBs; if (!hTp) { return TRANSPORTDEC_INVALID_PARAMETER; } hBs = &hTp->bitStream[layer]; switch (hTp->transportFmt) { case TT_MP4_ADIF: /* Read header if not already done */ if (!(hTp->flags & TPDEC_CONFIG_FOUND)) { CProgramConfig *pce; AudioSpecificConfig_Init(&hTp->asc[0]); pce = &hTp->asc[0].m_progrConfigElement; err = adifRead_DecodeHeader(&hTp->parser.adif, pce, hBs); if (err) goto bail; /* Map adif header to ASC */ hTp->asc[0].m_aot = (AUDIO_OBJECT_TYPE)(pce->Profile + 1); hTp->asc[0].m_samplingFrequencyIndex = pce->SamplingFrequencyIndex; hTp->asc[0].m_samplingFrequency = SamplingRateTable[pce->SamplingFrequencyIndex]; hTp->asc[0].m_channelConfiguration = 0; hTp->asc[0].m_samplesPerFrame = 1024; hTp->avgBitRate = hTp->parser.adif.BitRate; /* Call callback to decoder. */ { int errC; errC = hTp->callbacks.cbUpdateConfig(hTp->callbacks.cbUpdateConfigData, &hTp->asc[0]); if (errC == 0) { hTp->flags |= TPDEC_CONFIG_FOUND; } else { err = TRANSPORTDEC_PARSE_ERROR; goto bail; } } } hTp->auLength[layer] = -1; /* Access Unit data length is unknown. */ break; case TT_MP4_RAW: if ((INT)FDKgetValidBits(hBs) <= 0 && layer == 0) { err = TRANSPORTDEC_NOT_ENOUGH_BITS; } /* One Access Unit was filled into buffer. So get the length out of the buffer. */ hTp->auLength[layer] = FDKgetValidBits(hBs); hTp->flags |= TPDEC_SYNCOK; break; case TT_RSVD50: case TT_MP4_ADTS: case TT_MP4_LOAS: case TT_MP4_LATM_MCP0: case TT_MP4_LATM_MCP1: err = transportDec_readStream(hTp, layer); break; default: err = TRANSPORTDEC_UNSUPPORTED_FORMAT; break; } if (err == TRANSPORTDEC_OK) { hTp->accessUnitAnchor[layer] = FDKgetValidBits(hBs); } else { hTp->accessUnitAnchor[layer] = 0; } bail: return err; }
TRANSPORTDEC_ERROR AudioSpecificConfig_Parse( CSAudioSpecificConfig *self, HANDLE_FDK_BITSTREAM bs, int fExplicitBackwardCompatible, CSTpCallBacks *cb ) { TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; UINT ascStartAnchor = FDKgetValidBits(bs); int frameLengthFlag = -1; AudioSpecificConfig_Init(self); self->m_aot = getAOT(bs); self->m_samplingFrequency = getSampleRate(bs, &self->m_samplingFrequencyIndex, 4); if (self->m_samplingFrequency <= 0) { return TRANSPORTDEC_PARSE_ERROR; } self->m_channelConfiguration = FDKreadBits(bs,4); /* SBR extension ( explicit non-backwards compatible mode ) */ self->m_sbrPresentFlag = 0; self->m_psPresentFlag = 0; if ( self->m_aot == AOT_SBR || self->m_aot == AOT_PS ) { self->m_extensionAudioObjectType = AOT_SBR; self->m_sbrPresentFlag = 1; if ( self->m_aot == AOT_PS ) { self->m_psPresentFlag = 1; } self->m_extensionSamplingFrequency = getSampleRate(bs, &self->m_extensionSamplingFrequencyIndex, 4); self->m_aot = getAOT(bs); } else { self->m_extensionAudioObjectType = AOT_NULL_OBJECT; } /* Parse whatever specific configs */ switch (self->m_aot) { #ifdef TP_GA_ENABLE case AOT_AAC_LC: case AOT_ER_AAC_LC: case AOT_ER_AAC_LD: case AOT_ER_AAC_SCAL: case AOT_ER_BSAC: if ((ErrorStatus = GaSpecificConfig_Parse(&self->m_sc.m_gaSpecificConfig, self, bs, ascStartAnchor)) != TRANSPORTDEC_OK ) { return (ErrorStatus); } frameLengthFlag = self->m_sc.m_gaSpecificConfig.m_frameLengthFlag; break; #endif /* TP_GA_ENABLE */ case AOT_MPEGS: if (cb->cbSsc != NULL) { cb->cbSsc( cb->cbSscData, bs, self->m_aot, self->m_samplingFrequency, 1, 0 /* don't know the length */ ); } else { return TRANSPORTDEC_UNSUPPORTED_FORMAT; } break; #ifdef TP_ELD_ENABLE case AOT_ER_AAC_ELD: if ((ErrorStatus = EldSpecificConfig_Parse(self, bs, cb)) != TRANSPORTDEC_OK ) { return (ErrorStatus); } frameLengthFlag = self->m_sc.m_eldSpecificConfig.m_frameLengthFlag; self->m_sbrPresentFlag = self->m_sc.m_eldSpecificConfig.m_sbrPresentFlag; self->m_extensionSamplingFrequency = (self->m_sc.m_eldSpecificConfig.m_sbrSamplingRate+1) * self->m_samplingFrequency; break; #endif /* TP_ELD_ENABLE */ default: return TRANSPORTDEC_UNSUPPORTED_FORMAT; break; } /* Frame length */ switch (self->m_aot) { #if defined(TP_GA_ENABLE) || defined(TP_USAC_ENABLE) case AOT_AAC_LC: case AOT_ER_AAC_LC: case AOT_ER_AAC_SCAL: case AOT_ER_BSAC: /*case AOT_USAC:*/ if (!frameLengthFlag) self->m_samplesPerFrame = 1024; else self->m_samplesPerFrame = 960; break; #endif /* TP_GA_ENABLE */ #if defined(TP_GA_ENABLE) case AOT_ER_AAC_LD: if (!frameLengthFlag) self->m_samplesPerFrame = 512; else self->m_samplesPerFrame = 480; break; #endif /* defined(TP_GA_ENABLE) */ default: break; } switch (self->m_aot) { case AOT_ER_AAC_LC: case AOT_ER_AAC_LD: case AOT_ER_AAC_ELD: case AOT_ER_AAC_SCAL: case AOT_ER_CELP: case AOT_ER_HVXC: case AOT_ER_BSAC: self->m_epConfig = FDKreadBits(bs,2); if (self->m_epConfig > 1) { return TRANSPORTDEC_UNSUPPORTED_FORMAT; // EPCONFIG; } break; default: break; } if (fExplicitBackwardCompatible) { ErrorStatus = AudioSpecificConfig_ExtensionParse(self, bs, cb); } return (ErrorStatus); }
static TRANSPORTDEC_ERROR transportDec_readHeader( HANDLE_TRANSPORTDEC hTp, HANDLE_FDK_BITSTREAM hBs, int syncLength, int ignoreBufferFullness, int *pRawDataBlockLength, int *pfTraverseMoreFrames, int *pSyncLayerFrameBits, int *pfConfigFound, int *pHeaderBits ) { TRANSPORTDEC_ERROR err = TRANSPORTDEC_OK; int rawDataBlockLength = *pRawDataBlockLength; int fTraverseMoreFrames = (pfTraverseMoreFrames != NULL) ? *pfTraverseMoreFrames : 0; int syncLayerFrameBits = (pSyncLayerFrameBits != NULL) ? *pSyncLayerFrameBits : 0; int fConfigFound = (pfConfigFound != NULL) ? *pfConfigFound : 0; int startPos; startPos = FDKgetValidBits(hBs); switch (hTp->transportFmt) { case TT_MP4_ADTS: if (hTp->numberOfRawDataBlocks <= 0) { int errC; hTp->globalFramePos = FDKgetValidBits(hBs); /* 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) { if (errC == TRANSPORTDEC_NEED_TO_RESTART) { err = TRANSPORTDEC_NEED_TO_RESTART; goto bail; } else { err = TRANSPORTDEC_SYNC_ERROR; } } else { fConfigFound = 1; hTp->numberOfRawDataBlocks = hTp->parser.adts.bs.num_raw_blocks+1; } } } else { /* Reset CRC because the next bits are the beginning of a raw_data_block() */ FDKcrcReset(&hTp->parser.adts.crcInfo); hTp->parser.adts.bs.num_pce_bits = 0; } if (err == TRANSPORTDEC_OK) { hTp->numberOfRawDataBlocks--; rawDataBlockLength = adtsRead_GetRawDataBlockLength(&hTp->parser.adts, (hTp->parser.adts.bs.num_raw_blocks-hTp->numberOfRawDataBlocks)); if (rawDataBlockLength <= 0) { /* No further frame traversal possible. */ fTraverseMoreFrames = 0; } 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, &fConfigFound, ignoreBufferFullness); if (err != TRANSPORTDEC_OK) { if (err != TRANSPORTDEC_NOT_ENOUGH_BITS) { err = TRANSPORTDEC_SYNC_ERROR; } } else { hTp->numberOfRawDataBlocks = CLatmDemux_GetNrOfSubFrames(&hTp->parser.latm); if (hTp->transportFmt == TT_MP4_LOAS) { 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; } bail: *pRawDataBlockLength = rawDataBlockLength; if (pHeaderBits != NULL) { *pHeaderBits += startPos - (INT)FDKgetValidBits(hBs); } if (pfConfigFound != NULL) { *pfConfigFound = fConfigFound; } if (pfTraverseMoreFrames != NULL) { *pfTraverseMoreFrames = fTraverseMoreFrames; } if (pSyncLayerFrameBits != NULL) { *pSyncLayerFrameBits = syncLayerFrameBits; } if (pfConfigFound != NULL) { *pfConfigFound = fConfigFound; } return err; }
int adtsWrite_EncodeHeader(HANDLE_ADTS hAdts, HANDLE_FDK_BITSTREAM hBitStream, int buffer_fullness, int frame_length) { INT crcIndex = 0; hAdts->headerBits = adtsWrite_GetHeaderBits(hAdts); FDK_ASSERT(((frame_length+hAdts->headerBits)/8)<0x2000); /*13 bit*/ FDK_ASSERT(buffer_fullness<0x800); /* 11 bit */ if (!hAdts->protection_absent) { FDKcrcReset(&hAdts->crcInfo); } if (hAdts->currentBlock == 0) { FDKresetBitbuffer(hBitStream, BS_WRITER); } hAdts->subFrameStartBit = FDKgetValidBits(hBitStream); /* Skip new header if this is raw data block 1..n */ if (hAdts->currentBlock == 0) { FDKresetBitbuffer(hBitStream, BS_WRITER); if (hAdts->num_raw_blocks == 0) { crcIndex = adtsWrite_CrcStartReg(hAdts, hBitStream, 0); } /* fixed header */ FDKwriteBits(hBitStream, 0xFFF, 12); FDKwriteBits(hBitStream, hAdts->mpeg_id, 1); FDKwriteBits(hBitStream, hAdts->layer, 2); FDKwriteBits(hBitStream, hAdts->protection_absent, 1); FDKwriteBits(hBitStream, hAdts->profile, 2); FDKwriteBits(hBitStream, hAdts->sample_freq_index, 4); FDKwriteBits(hBitStream, hAdts->private_bit, 1); FDKwriteBits(hBitStream, getChannelConfig(hAdts->channel_mode), 3); FDKwriteBits(hBitStream, hAdts->original, 1); FDKwriteBits(hBitStream, hAdts->home, 1); /* variable header */ FDKwriteBits(hBitStream, hAdts->copyright_id, 1); FDKwriteBits(hBitStream, hAdts->copyright_start, 1); FDKwriteBits(hBitStream, (frame_length + hAdts->headerBits)>>3, 13); FDKwriteBits(hBitStream, buffer_fullness, 11); FDKwriteBits(hBitStream, hAdts->num_raw_blocks, 2); if (!hAdts->protection_absent) { int i; /* End header CRC portion for single raw data block and write dummy zero values for unknown fields. */ if (hAdts->num_raw_blocks == 0) { adtsWrite_CrcEndReg(hAdts, hBitStream, crcIndex); } else { for (i=0; i<hAdts->num_raw_blocks; i++) { FDKwriteBits(hBitStream, 0, 16); } } FDKwriteBits(hBitStream, 0, 16); } } /* End of ADTS header */