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; }
int CProgramConfig_GetElementTable( const CProgramConfig *pPce, MP4_ELEMENT_ID elList[], const INT elListSize, UCHAR *pChMapIdx ) { int i, el = 0; FDK_ASSERT(elList != NULL); FDK_ASSERT(pChMapIdx != NULL); *pChMapIdx = 0; if ( elListSize < pPce->NumFrontChannelElements + pPce->NumSideChannelElements + pPce->NumBackChannelElements + pPce->NumLfeChannelElements ) { return 0; } for (i=0; i < pPce->NumFrontChannelElements; i++) { elList[el++] = (pPce->FrontElementIsCpe[i]) ? ID_CPE : ID_SCE; } for (i=0; i < pPce->NumSideChannelElements; i++) { elList[el++] = (pPce->SideElementIsCpe[i]) ? ID_CPE : ID_SCE; } for (i=0; i < pPce->NumBackChannelElements; i++) { elList[el++] = (pPce->BackElementIsCpe[i]) ? ID_CPE : ID_SCE; } for (i=0; i < pPce->NumLfeChannelElements; i++) { elList[el++] = ID_LFE; } /* Find an corresponding channel configuration if possible */ switch (pPce->NumChannels) { case 1: case 2: case 3: case 4: case 5: case 6: /* One and two channels have no alternatives. The other ones are mapped directly to the corresponding channel config. Because of legacy reasons or for lack of alternative mappings. */ *pChMapIdx = pPce->NumChannels; break; case 7: { C_ALLOC_SCRATCH_START(tmpPce, CProgramConfig, 1); /* Create a PCE for the config to test ... */ CProgramConfig_GetDefault(tmpPce, 11); /* ... and compare it with the given one. */ *pChMapIdx = (!(CProgramConfig_Compare(pPce, tmpPce)&0xE)) ? 11 : 0; /* If compare result is 0 or 1 we can be sure that it is channel config 11. */ C_ALLOC_SCRATCH_END(tmpPce, CProgramConfig, 1); } break; case 8: { /* Try the four possible 7.1ch configurations. One after the other. */ UCHAR testCfg[4] = { 32, 14, 12, 7}; C_ALLOC_SCRATCH_START(tmpPce, CProgramConfig, 1); for (i=0; i<4; i+=1) { /* Create a PCE for the config to test ... */ CProgramConfig_GetDefault(tmpPce, testCfg[i]); /* ... and compare it with the given one. */ if (!(CProgramConfig_Compare(pPce, tmpPce)&0xE)) { /* If the compare result is 0 or 1 than the two channel configurations match. */ /* Explicit mapping of 7.1 side channel configuration to 7.1 rear channel mapping. */ *pChMapIdx = (testCfg[i]==32) ? 12 : testCfg[i]; } } C_ALLOC_SCRATCH_END(tmpPce, CProgramConfig, 1); } break; default: /* The PCE does not match any predefined channel configuration. */ *pChMapIdx = 0; break; } return el; }
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 FDKaacEnc_groupShortData(FIXP_DBL *mdctSpectrum, /* in-out */ SFB_THRESHOLD *sfbThreshold, /* in-out */ SFB_ENERGY *sfbEnergy, /* in-out */ SFB_ENERGY *sfbEnergyMS, /* in-out */ SFB_ENERGY *sfbSpreadEnergy, const INT sfbCnt, const INT sfbActive, const INT *sfbOffset, const FIXP_DBL *sfbMinSnrLdData, INT *groupedSfbOffset, /* out */ INT *maxSfbPerGroup, /* out */ FIXP_DBL *groupedSfbMinSnrLdData, const INT noOfGroups, const INT *groupLen, const INT granuleLength) { INT i,j; INT line; /* counts through lines */ INT sfb; /* counts through scalefactor bands */ INT grp; /* counts through groups */ INT wnd; /* counts through windows in a group */ INT offset; /* needed in sfbOffset grouping */ INT highestSfb; INT granuleLength_short = granuleLength/TRANS_FAC; /* for short blocks: regroup spectrum and */ /* group energies and thresholds according to grouping */ C_ALLOC_SCRATCH_START(tmpSpectrum, FIXP_DBL, (1024)); /* calculate maxSfbPerGroup */ highestSfb = 0; for (wnd = 0; wnd < TRANS_FAC; wnd++) { for (sfb = sfbActive-1; sfb >= highestSfb; sfb--) { for (line = sfbOffset[sfb+1]-1; line >= sfbOffset[sfb]; line--) { if ( mdctSpectrum[wnd*granuleLength_short+line] != FL2FXCONST_SPC(0.0) ) break; /* this band is not completely zero */ } if (line >= sfbOffset[sfb]) break; /* this band was not completely zero */ } highestSfb = fixMax(highestSfb, sfb); } highestSfb = highestSfb > 0 ? highestSfb : 0; *maxSfbPerGroup = highestSfb+1; /* calculate groupedSfbOffset */ i = 0; offset = 0; for (grp = 0; grp < noOfGroups; grp++) { for (sfb = 0; sfb < sfbActive+1; sfb++) { groupedSfbOffset[i++] = offset + sfbOffset[sfb] * groupLen[grp]; } i += sfbCnt-sfb; offset += groupLen[grp] * granuleLength_short; } groupedSfbOffset[i++] = granuleLength; /* calculate groupedSfbMinSnr */ i = 0; for (grp = 0; grp < noOfGroups; grp++) { for (sfb = 0; sfb < sfbActive; sfb++) { groupedSfbMinSnrLdData[i++] = sfbMinSnrLdData[sfb]; } i += sfbCnt-sfb; } /* sum up sfbThresholds */ wnd = 0; i = 0; for (grp = 0; grp < noOfGroups; grp++) { for (sfb = 0; sfb < sfbActive; sfb++) { FIXP_DBL thresh = sfbThreshold->Short[wnd][sfb]; for (j=1; j<groupLen[grp]; j++) { thresh = nrgAddSaturate(thresh, sfbThreshold->Short[wnd+j][sfb]); } sfbThreshold->Long[i++] = thresh; } i += sfbCnt-sfb; wnd += groupLen[grp]; } /* sum up sfbEnergies left/right */ wnd = 0; i = 0; for (grp = 0; grp < noOfGroups; grp++) { for (sfb = 0; sfb < sfbActive; sfb++) { FIXP_DBL energy = sfbEnergy->Short[wnd][sfb]; for (j=1; j<groupLen[grp]; j++) { energy = nrgAddSaturate(energy, sfbEnergy->Short[wnd+j][sfb]); } sfbEnergy->Long[i++] = energy; } i += sfbCnt-sfb; wnd += groupLen[grp]; } /* sum up sfbEnergies mid/side */ wnd = 0; i = 0; for (grp = 0; grp < noOfGroups; grp++) { for (sfb = 0; sfb < sfbActive; sfb++) { FIXP_DBL energy = sfbEnergyMS->Short[wnd][sfb]; for (j=1; j<groupLen[grp]; j++) { energy = nrgAddSaturate(energy, sfbEnergyMS->Short[wnd+j][sfb]); } sfbEnergyMS->Long[i++] = energy; } i += sfbCnt-sfb; wnd += groupLen[grp]; } /* sum up sfbSpreadEnergies */ wnd = 0; i = 0; for (grp = 0; grp < noOfGroups; grp++) { for (sfb = 0; sfb < sfbActive; sfb++) { FIXP_DBL energy = sfbSpreadEnergy->Short[wnd][sfb]; for (j=1; j<groupLen[grp]; j++) { energy = nrgAddSaturate(energy, sfbSpreadEnergy->Short[wnd+j][sfb]); } sfbSpreadEnergy->Long[i++] = energy; } i += sfbCnt-sfb; wnd += groupLen[grp]; } /* re-group spectrum */ wnd = 0; i = 0; for (grp = 0; grp < noOfGroups; grp++) { for (sfb = 0; sfb < sfbActive; sfb++) { int width = sfbOffset[sfb+1]-sfbOffset[sfb]; FIXP_DBL *pMdctSpectrum = &mdctSpectrum[sfbOffset[sfb]] + wnd*granuleLength_short; for (j = 0; j < groupLen[grp]; j++) { FIXP_DBL *pTmp = pMdctSpectrum; for (line = width; line > 0; line--) { tmpSpectrum[i++] = *pTmp++; } pMdctSpectrum += granuleLength_short; } } i += (groupLen[grp]*(sfbOffset[sfbCnt]-sfbOffset[sfb])); wnd += groupLen[grp]; } FDKmemcpy(mdctSpectrum, tmpSpectrum, granuleLength*sizeof(FIXP_DBL)); C_ALLOC_SCRATCH_END(tmpSpectrum, FIXP_DBL, (1024)) }
static void CTns_Filter (FIXP_DBL *spec, int size, int inc, FIXP_TCC coeff [], int order) { // - Simple all-pole filter of order "order" defined by // y(n) = x(n) - a(2)*y(n-1) - ... - a(order+1)*y(n-order) // // - The state variables of the filter are initialized to zero every time // // - The output data is written over the input data ("in-place operation") // // - An input vector of "size" samples is processed and the index increment // to the next data sample is given by "inc" int i,j,N; FIXP_DBL *pSpec; FIXP_DBL maxVal=FL2FXCONST_DBL(0.0); INT s; FDK_ASSERT(order <= TNS_MAXIMUM_ORDER); C_ALLOC_SCRATCH_START(state, FIXP_DBL, TNS_MAXIMUM_ORDER); FDKmemclear(state, order*sizeof(FIXP_DBL)); for (i=0; i<size; i++) { maxVal = fixMax(maxVal,fixp_abs(spec[i])); } if ( maxVal > FL2FXCONST_DBL(0.03125*0.70710678118) ) s = fixMax(CntLeadingZeros(maxVal)-6,0); else s = fixMax(CntLeadingZeros(maxVal)-5,0); s = fixMin(s,2); s = s-1; if (inc == -1) pSpec = &spec[size - 1]; else pSpec = &spec[0]; FIXP_TCC *pCoeff; #define FIRST_PART_FLTR \ FIXP_DBL x, *pState = state; \ pCoeff = coeff; \ \ if (s < 0) \ x = (pSpec [0]>>1) + fMultDiv2 (*pCoeff++, pState [0]) ; \ else \ x = (pSpec [0]<<s) + fMultDiv2 (*pCoeff++, pState [0]) ; #define INNER_FLTR_INLINE \ x = fMultAddDiv2 (x, *pCoeff, pState [1]); \ pState [0] = pState [1] - (fMultDiv2 (*pCoeff++, x) <<2) ; \ pState++; #define LAST_PART_FLTR \ if (s < 0) \ *pSpec = x << 1; \ else \ *pSpec = x >> s; \ *pState =(-x) << 1; \ pSpec += inc ; if (order>8) { N = (order-1)&7; for (i = size ; i != 0 ; i--) { FIRST_PART_FLTR for (j = N; j > 0 ; j--) { INNER_FLTR_INLINE } INNER_FLTR_INLINE INNER_FLTR_INLINE INNER_FLTR_INLINE INNER_FLTR_INLINE INNER_FLTR_INLINE INNER_FLTR_INLINE INNER_FLTR_INLINE INNER_FLTR_INLINE LAST_PART_FLTR } } else if (order>4) {