INT FDKsbrEnc_InitSbrBitstream(HANDLE_COMMON_DATA hCmonData, UCHAR *memoryBase, /*!< Pointer to bitstream buffer */ INT memorySize, /*!< Length of bitstream buffer in bytes */ HANDLE_FDK_CRCINFO hCrcInfo, UINT sbrSyntaxFlags) /*!< SBR syntax flags */ { INT crcRegion = 0; /* reset bit buffer */ FDKresetBitbuffer(&hCmonData->sbrBitbuf, BS_WRITER); FDKinitBitStream(&hCmonData->tmpWriteBitbuf, memoryBase, memorySize, 0, BS_WRITER); if (sbrSyntaxFlags & SBR_SYNTAX_CRC) { if (sbrSyntaxFlags & SBR_SYNTAX_DRM_CRC) { /* Init and start CRC region */ FDKwriteBits (&hCmonData->sbrBitbuf, 0x0, SI_SBR_DRM_CRC_BITS); FDKcrcInit( hCrcInfo, 0x001d, 0xFFFF, SI_SBR_DRM_CRC_BITS ); crcRegion = FDKcrcStartReg( hCrcInfo, &hCmonData->sbrBitbuf, 0 ); } else { FDKwriteBits (&hCmonData->sbrBitbuf, 0x0, SI_SBR_CRC_BITS); } } return (crcRegion); }
HANDLE_TRANSPORTDEC transportDec_Open( const TRANSPORT_TYPE transportFmt, const UINT flags) { HANDLE_TRANSPORTDEC hInput; hInput = GetRam_TransportDecoder(0); if ( hInput == NULL ) { return NULL; } /* Init transportDec struct. */ hInput->transportFmt = transportFmt; switch (transportFmt) { case TT_MP4_ADIF: break; case TT_MP4_ADTS: if (flags & TP_FLAG_MPEG4) hInput->parser.adts.decoderCanDoMpeg4 = 1; else hInput->parser.adts.decoderCanDoMpeg4 = 0; adtsRead_CrcInit(&hInput->parser.adts); hInput->parser.adts.BufferFullnesStartFlag = 1; hInput->numberOfRawDataBlocks = 0; break; case TT_MP4_LATM_MCP0: case TT_MP4_LATM_MCP1: case TT_MP4_LOAS: case TT_MP4_RAW: break; default: FreeRam_TransportDecoder(&hInput); hInput = NULL; break; } if (hInput != NULL) { /* Create bitstream */ if ( (transportFmt == TT_MP4_RAW) || (transportFmt == TT_DRM) ){ hInput->bsBuffer = NULL; } else { hInput->bsBuffer = GetRam_TransportDecoderBuffer(0); if (hInput->bsBuffer == NULL) { transportDec_Close( &hInput ); return NULL; } FDKinitBitStream(&hInput->bitStream[0], hInput->bsBuffer, TRANSPORTDEC_INBUF_SIZE, 0, BS_READER); } hInput->burstPeriod = 0; } return hInput; }
TRANSPORTDEC_ERROR transportDec_OutOfBandConfig(HANDLE_TRANSPORTDEC hTp, UCHAR *conf, const UINT length, UINT layer ) { TRANSPORTDEC_ERROR err = TRANSPORTDEC_OK; FDK_BITSTREAM bs; HANDLE_FDK_BITSTREAM hBs = &bs; FDKinitBitStream(hBs, conf, 0x10000000, length<<3, BS_READER); int fConfigFound = 0; /* config transport decoder */ switch (hTp->transportFmt) { case TT_MP4_LATM_MCP0: case TT_MP4_LATM_MCP1: case TT_MP4_LOAS: { if (layer != 0) { return TRANSPORTDEC_INVALID_PARAMETER; } CLatmDemux *pLatmDemux = &hTp->parser.latm; err = CLatmDemux_ReadStreamMuxConfig(hBs, pLatmDemux, &hTp->callbacks, hTp->asc, &fConfigFound); if (err != TRANSPORTDEC_OK) { return err; } } break; default: fConfigFound = 1; err = AudioSpecificConfig_Parse(&hTp->asc[layer], hBs, 1, &hTp->callbacks); if (err == TRANSPORTDEC_OK) { int errC; errC = hTp->callbacks.cbUpdateConfig(hTp->callbacks.cbUpdateConfigData, &hTp->asc[layer]); if (errC != 0) { err = TRANSPORTDEC_PARSE_ERROR; } } break; case TT_DRM: fConfigFound = 1; err = DrmRawSdcAudioConfig_Parse(&hTp->asc[layer], hBs); if (err == TRANSPORTDEC_OK) { int errC; errC = hTp->callbacks.cbUpdateConfig(hTp->callbacks.cbUpdateConfigData, &hTp->asc[layer]); if (errC != 0) { err = TRANSPORTDEC_PARSE_ERROR; } } break; } if (err == TRANSPORTDEC_OK && fConfigFound) { hTp->flags |= TPDEC_CONFIG_FOUND; } return err; }
TRANSPORTDEC_ERROR transportDec_FillData( const HANDLE_TRANSPORTDEC hTp, UCHAR *pBuffer, const UINT bufferSize, UINT *pBytesValid, const INT layer ) { HANDLE_FDK_BITSTREAM hBs; if ( (hTp == NULL) || (layer >= 2) ) { return TRANSPORTDEC_INVALID_PARAMETER; } if (*pBytesValid == 0) { /* nothing to do */ return TRANSPORTDEC_OK; } /* set bitbuffer shortcut */ hBs = &hTp->bitStream[layer]; switch (hTp->transportFmt) { case TT_MP4_RAW: case TT_DRM: /* For packet based transport, pass input buffer to bitbuffer without copying the data. Unfortunately we do not know the actual buffer size. And the FDK bit buffer implementation needs a number 2^x. So we assume the maximum of 48 channels with 6144 bits per channel and round it up to the next power of 2 => 65536 bytes */ FDKinitBitStream(hBs, pBuffer, 0x10000, (*pBytesValid)<<3, BS_READER); *pBytesValid = 0; break; default: /* ... else feed bitbuffer with new stream data (append). */ if (hTp->numberOfRawDataBlocks <= 0) { FDKfeedBuffer (hBs, pBuffer, bufferSize, pBytesValid) ; } } return TRANSPORTDEC_OK; }
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; }
TRANSPORTENC_ERROR transportEnc_Init( HANDLE_TRANSPORTENC hTpEnc, UCHAR *bsBuffer, INT bsBufferSize, TRANSPORT_TYPE transportFmt, CODER_CONFIG *cconfig, UINT flags ) { /* Copy configuration structure */ FDKmemcpy(&hTpEnc->config, cconfig, sizeof(CODER_CONFIG)); /* Init transportEnc struct. */ hTpEnc->transportFmt = transportFmt; hTpEnc->bsBuffer = bsBuffer; hTpEnc->bsBufferSize = bsBufferSize; FDKinitBitStream(&hTpEnc->bitStream, hTpEnc->bsBuffer, hTpEnc->bsBufferSize, 0, BS_WRITER); switch (transportFmt) { case TT_MP4_ADIF: /* Sanity checks */ if ( (hTpEnc->config.aot != AOT_AAC_LC) ||(hTpEnc->config.samplesPerFrame != 1024)) { return TRANSPORTENC_INVALID_PARAMETER; } hTpEnc->writer.adif.headerWritten = 0; hTpEnc->writer.adif.samplingRate = hTpEnc->config.samplingRate; hTpEnc->writer.adif.bitRate = hTpEnc->config.bitRate; hTpEnc->writer.adif.profile = ((int)hTpEnc->config.aot) - 1; hTpEnc->writer.adif.cm = hTpEnc->config.channelMode; hTpEnc->writer.adif.bVariableRate = 0; hTpEnc->writer.adif.instanceTag = 0; break; case TT_MP4_ADTS: /* Sanity checks */ if ( ( hTpEnc->config.aot != AOT_AAC_LC) ||(hTpEnc->config.samplesPerFrame != 1024) ) { return TRANSPORTENC_INVALID_PARAMETER; } if ( adtsWrite_Init(&hTpEnc->writer.adts, &hTpEnc->config) != 0) { return TRANSPORTENC_INVALID_PARAMETER; } break; case TT_DABPLUS: /* Sanity checks */ if ( ( hTpEnc->config.aot != AOT_AAC_LC) ||(hTpEnc->config.samplesPerFrame != 960) ) { return TRANSPORTENC_INVALID_PARAMETER; } if ( dabWrite_Init(&hTpEnc->writer.dab, &hTpEnc->config) != 0) { return TRANSPORTENC_INVALID_PARAMETER; } break; case TT_MP4_LOAS: case TT_MP4_LATM_MCP0: case TT_MP4_LATM_MCP1: { TRANSPORTENC_ERROR error; error = transportEnc_Latm_Init( &hTpEnc->writer.latm, &hTpEnc->bitStream, &hTpEnc->config, flags & TP_FLAG_LATM_AMV, transportFmt, &hTpEnc->callbacks ); if (error != TRANSPORTENC_OK) { return error; } } break; case TT_MP4_RAW: hTpEnc->writer.raw.curSubFrame = 0; hTpEnc->writer.raw.nSubFrames = hTpEnc->config.nSubFrames; break; default: return TRANSPORTENC_INVALID_PARAMETER; } /* pceFrameCounter indicates if PCE must be written in raw_data_block. */ hTpEnc->pceFrameCounter = getPceRepetitionRate( getChannelConfig(hTpEnc->config.channelMode), transportFmt, hTpEnc->config.headerPeriod, hTpEnc->config.matrixMixdownA); return TRANSPORTENC_OK; }
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); }