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; }
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 = (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 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); }
TRANSPORTDEC_ERROR adtsRead_DecodeHeader( HANDLE_ADTS pAdts, CSAudioSpecificConfig *pAsc, HANDLE_FDK_BITSTREAM hBs, const INT ignoreBufferFullness ) { INT crcReg; INT valBits; INT cmp_buffer_fullness; int i, adtsHeaderLength; STRUCT_ADTS_BS bs; #ifdef TP_PCE_ENABLE CProgramConfig oldPce; /* Store the old PCE temporarily. Maybe we'll need it later if we have channelConfig=0 and no PCE in this frame. */ FDKmemcpy(&oldPce, &pAsc->m_progrConfigElement, sizeof(CProgramConfig)); #endif valBits = FDKgetValidBits(hBs); #ifndef ANDROID_DEFAULT_CODE if (valBits <= ADTS_HEADERLENGTH) return TRANSPORTDEC_NOT_ENOUGH_BITS; #endif /* adts_fixed_header */ bs.mpeg_id = FDKreadBits(hBs, Adts_Length_Id); bs.layer = FDKreadBits(hBs, Adts_Length_Layer); bs.protection_absent = FDKreadBits(hBs, Adts_Length_ProtectionAbsent); bs.profile = FDKreadBits(hBs, Adts_Length_Profile); bs.sample_freq_index = FDKreadBits(hBs, Adts_Length_SamplingFrequencyIndex); bs.private_bit = FDKreadBits(hBs, Adts_Length_PrivateBit); bs.channel_config = FDKreadBits(hBs, Adts_Length_ChannelConfiguration); bs.original = FDKreadBits(hBs, Adts_Length_OriginalCopy); bs.home = FDKreadBits(hBs, Adts_Length_Home); /* adts_variable_header */ bs.copyright_id = FDKreadBits(hBs, Adts_Length_CopyrightIdentificationBit); bs.copyright_start = FDKreadBits(hBs, Adts_Length_CopyrightIdentificationStart); bs.frame_length = FDKreadBits(hBs, Adts_Length_FrameLength); bs.adts_fullness = FDKreadBits(hBs, Adts_Length_BufferFullness); bs.num_raw_blocks = FDKreadBits(hBs, Adts_Length_NumberOfRawDataBlocksInFrame); bs.num_pce_bits = 0; adtsHeaderLength = ADTS_HEADERLENGTH; if (!bs.protection_absent) { FDKcrcReset(&pAdts->crcInfo); FDKpushBack(hBs, 56); /* complete fixed and variable header! */ crcReg = FDKcrcStartReg(&pAdts->crcInfo, hBs, 0); FDKpushFor(hBs, 56); } if (! bs.protection_absent && bs.num_raw_blocks>0) { for (i=0; i<bs.num_raw_blocks; i++) { pAdts->rawDataBlockDist[i] = (USHORT)FDKreadBits(hBs, 16); adtsHeaderLength += 16; } /* Change raw data blocks to delta values */ pAdts->rawDataBlockDist[bs.num_raw_blocks] = bs.frame_length - 7 - bs.num_raw_blocks*2 - 2 ; for (i=bs.num_raw_blocks; i>0; i--) { pAdts->rawDataBlockDist[i] -= pAdts->rawDataBlockDist[i-1]; } } /* adts_error_check */ if (!bs.protection_absent) { USHORT crc_check; FDKcrcEndReg(&pAdts->crcInfo, hBs, crcReg); crc_check = FDKreadBits(hBs, Adts_Length_CrcCheck); adtsHeaderLength += Adts_Length_CrcCheck; pAdts->crcReadValue = crc_check; /* Check header CRC in case of multiple raw data blocks */ if (bs.num_raw_blocks > 0) { if (pAdts->crcReadValue != FDKcrcGetCRC(&pAdts->crcInfo)) { return TRANSPORTDEC_CRC_ERROR; } /* Reset CRC for the upcoming raw_data_block() */ FDKcrcReset(&pAdts->crcInfo); } } /* check if valid header */ if ( (bs.layer != 0) || // we only support MPEG ADTS (bs.sample_freq_index >= 13) // we only support 96kHz - 7350kHz ) { FDKpushFor(hBs, bs.frame_length * 8); // try again one frame later return TRANSPORTDEC_UNSUPPORTED_FORMAT; } /* special treatment of id-bit */ if ( (bs.mpeg_id == 0) && (pAdts->decoderCanDoMpeg4 == 0) ) { /* MPEG-2 decoder cannot play MPEG-4 bitstreams */ FDKpushFor(hBs, bs.frame_length * 8); // try again one frame later return TRANSPORTDEC_UNSUPPORTED_FORMAT; } if (!ignoreBufferFullness) { cmp_buffer_fullness = bs.frame_length*8 + bs.adts_fullness*32*getNumberOfEffectiveChannels(bs.channel_config); /* Evaluate buffer fullness */ if (bs.adts_fullness != 0x7FF) { if (pAdts->BufferFullnesStartFlag) { if ( valBits < cmp_buffer_fullness ) { /* Condition for start of decoding is not fulfilled */ /* The current frame will not be decoded */ FDKpushBack(hBs, adtsHeaderLength); if ( (cmp_buffer_fullness+adtsHeaderLength) > ((TRANSPORTDEC_INBUF_SIZE<<3)-7) ) { return TRANSPORTDEC_SYNC_ERROR; } else { return TRANSPORTDEC_NOT_ENOUGH_BITS; } } else { pAdts->BufferFullnesStartFlag = 0; } } } } /* Get info from ADTS header */ AudioSpecificConfig_Init(pAsc); pAsc->m_aot = (AUDIO_OBJECT_TYPE)(bs.profile + 1); pAsc->m_samplingFrequencyIndex = bs.sample_freq_index; pAsc->m_samplingFrequency = SamplingRateTable[bs.sample_freq_index]; pAsc->m_channelConfiguration = bs.channel_config; pAsc->m_samplesPerFrame = 1024; #ifdef TP_PCE_ENABLE if (bs.channel_config == 0) { int pceBits = 0; UINT alignAnchor = FDKgetValidBits(hBs); if (FDKreadBits(hBs,3) == ID_PCE) { /* Got luck! Parse the PCE */ int crcReg; crcReg = adtsRead_CrcStartReg(pAdts, hBs, 0); CProgramConfig_Read(&pAsc->m_progrConfigElement, hBs, alignAnchor); adtsRead_CrcEndReg(pAdts, hBs, crcReg); pceBits = alignAnchor - FDKgetValidBits(hBs); /* store the number of PCE bits */ bs.num_pce_bits = pceBits; } else { /* No PCE in this frame! Push back the ID tag bits. */ FDKpushBack(hBs,3); /* Encoders do not have to write a PCE in each frame. So if we already have a valid PCE we have to use it. */ if ( oldPce.isValid && (bs.sample_freq_index == pAdts->bs.sample_freq_index) /* we could compare the complete fixed header (bytes) here! */ && (bs.channel_config == pAdts->bs.channel_config) /* == 0 */ && (bs.mpeg_id == pAdts->bs.mpeg_id) ) { /* Restore previous PCE which is still valid */ FDKmemcpy(&pAsc->m_progrConfigElement, &oldPce, sizeof(CProgramConfig)); } else if (bs.mpeg_id == 0) { /* If not it seems that we have a implicit channel configuration. This mode is not allowed in the context of ISO/IEC 14496-3. Skip this frame and try the next one. */ FDKpushFor(hBs, (bs.frame_length<<3) - adtsHeaderLength - 3); return TRANSPORTDEC_UNSUPPORTED_FORMAT; } /* else { ISO/IEC 13818-7 implicit channel mapping is allowed. So just open the box of chocolates to see what we got. } */ } } #endif /* TP_PCE_ENABLE */ /* Copy bit stream data struct to persistent memory now, once we passed all sanity checks above. */ FDKmemcpy(&pAdts->bs, &bs, sizeof(STRUCT_ADTS_BS)); return TRANSPORTDEC_OK; }