diff options
author | James Dong <jdong@google.com> | 2010-05-14 15:45:22 -0700 |
---|---|---|
committer | James Dong <jdong@google.com> | 2010-05-19 07:21:25 -0700 |
commit | 956c553ab0ce72f8074ad0fda2ffd66a0305700c (patch) | |
tree | fe111ecd29e01c270246f5f338c56806d6d5b136 /media/libstagefright/codecs/aacenc/src/bitenc.c | |
parent | e1f61055b4abb96a86d1ff24b5a7777dfe40fe5f (diff) | |
download | frameworks_av-956c553ab0ce72f8074ad0fda2ffd66a0305700c.zip frameworks_av-956c553ab0ce72f8074ad0fda2ffd66a0305700c.tar.gz frameworks_av-956c553ab0ce72f8074ad0fda2ffd66a0305700c.tar.bz2 |
Initial software encoder checkins
Change-Id: I27f387db23594e46384c4eb3a0093ce220bb6b60
Diffstat (limited to 'media/libstagefright/codecs/aacenc/src/bitenc.c')
-rw-r--r-- | media/libstagefright/codecs/aacenc/src/bitenc.c | 690 |
1 files changed, 690 insertions, 0 deletions
diff --git a/media/libstagefright/codecs/aacenc/src/bitenc.c b/media/libstagefright/codecs/aacenc/src/bitenc.c new file mode 100644 index 0000000..588c2da --- /dev/null +++ b/media/libstagefright/codecs/aacenc/src/bitenc.c @@ -0,0 +1,690 @@ +/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+/*******************************************************************************
+ File: bitenc.c
+
+ Content: Bitstream encoder functions
+
+*******************************************************************************/ + +#include "bitenc.h" +#include "bit_cnt.h" +#include "dyn_bits.h" +#include "qc_data.h" +#include "interface.h" + + +static const Word16 globalGainOffset = 100; +static const Word16 icsReservedBit = 0; + + +/***************************************************************************** +* +* function name: encodeSpectralData +* description: encode spectral data +* returns: spectral bits used +* +*****************************************************************************/ +static Word32 encodeSpectralData(Word16 *sfbOffset, + SECTION_DATA *sectionData, + Word16 *quantSpectrum, + HANDLE_BIT_BUF hBitStream) +{ + Word16 i,sfb; + Word16 dbgVal; + SECTION_INFO* psectioninfo; + dbgVal = GetBitsAvail(hBitStream); + + for(i=0; i<sectionData->noOfSections; i++) { + psectioninfo = &(sectionData->sectionInfo[i]);
+ /* + huffencode spectral data for this section + */ + for(sfb=psectioninfo->sfbStart; + sfb<psectioninfo->sfbStart+psectioninfo->sfbCnt; + sfb++) { + codeValues(quantSpectrum+sfbOffset[sfb], + sfbOffset[sfb+1] - sfbOffset[sfb], + psectioninfo->codeBook, + hBitStream); + } + } + + return(GetBitsAvail(hBitStream)-dbgVal); +} + +/***************************************************************************** +* +* function name:encodeGlobalGain +* description: encodes Global Gain (common scale factor) +* returns: none +* +*****************************************************************************/ +static void encodeGlobalGain(Word16 globalGain, + Word16 logNorm, + Word16 scalefac, + HANDLE_BIT_BUF hBitStream) +{ + WriteBits(hBitStream, ((globalGain - scalefac) + globalGainOffset-(logNorm << 2)), 8); +} + + +/***************************************************************************** +* +* function name:encodeIcsInfo +* description: encodes Ics Info +* returns: none +* +*****************************************************************************/ + +static void encodeIcsInfo(Word16 blockType, + Word16 windowShape, + Word16 groupingMask, + SECTION_DATA *sectionData, + HANDLE_BIT_BUF hBitStream) +{ + WriteBits(hBitStream,icsReservedBit,1); + WriteBits(hBitStream,blockType,2); + WriteBits(hBitStream,windowShape,1); + + + switch(blockType){ + case LONG_WINDOW: + case START_WINDOW: + case STOP_WINDOW: + WriteBits(hBitStream,sectionData->maxSfbPerGroup,6); + + /* No predictor data present */ + WriteBits(hBitStream, 0, 1); + break; + + case SHORT_WINDOW: + WriteBits(hBitStream,sectionData->maxSfbPerGroup,4); + + /* + Write grouping bits + */ + WriteBits(hBitStream,groupingMask,TRANS_FAC-1); + break; + } +} + +/***************************************************************************** +* +* function name: encodeSectionData +* description: encode section data (common Huffman codebooks for adjacent +* SFB's) +* returns: none +* +*****************************************************************************/ +static Word32 encodeSectionData(SECTION_DATA *sectionData, + HANDLE_BIT_BUF hBitStream) +{ + Word16 sectEscapeVal=0,sectLenBits=0; + Word16 sectLen; + Word16 i; + Word16 dbgVal=GetBitsAvail(hBitStream); + + + + 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++) { + WriteBits(hBitStream,sectionData->sectionInfo[i].codeBook,4); + sectLen = sectionData->sectionInfo[i].sfbCnt; + + while(sectLen >= sectEscapeVal) { + + WriteBits(hBitStream,sectEscapeVal,sectLenBits); + sectLen = sectLen - sectEscapeVal; + } + WriteBits(hBitStream,sectLen,sectLenBits); + } + return(GetBitsAvail(hBitStream)-dbgVal); +} + +/***************************************************************************** +* +* function name: encodeScaleFactorData +* description: encode DPCM coded scale factors +* returns: none +* +*****************************************************************************/ +static Word32 encodeScaleFactorData(UWord16 *maxValueInSfb, + SECTION_DATA *sectionData, + Word16 *scalefac, + HANDLE_BIT_BUF hBitStream) +{ + Word16 i,j,lastValScf,deltaScf; + Word16 dbgVal = GetBitsAvail(hBitStream); + SECTION_INFO* psectioninfo; + + lastValScf=scalefac[sectionData->firstScf]; + + for(i=0;i<sectionData->noOfSections;i++){ + psectioninfo = &(sectionData->sectionInfo[i]); + if (psectioninfo->codeBook != CODE_BOOK_ZERO_NO){ + for (j=psectioninfo->sfbStart; + j<psectioninfo->sfbStart+psectioninfo->sfbCnt; j++){ + + if(maxValueInSfb[j] == 0) { + deltaScf = 0; + } + else { + deltaScf = lastValScf - scalefac[j]; + lastValScf = scalefac[j]; + } + + if(codeScalefactorDelta(deltaScf,hBitStream)){ + return(1); + } + } + } + + } + return(GetBitsAvail(hBitStream)-dbgVal); +} + +/***************************************************************************** +* +* function name:encodeMsInfo +* description: encodes MS-Stereo Info +* returns: none +* +*****************************************************************************/ +static void encodeMSInfo(Word16 sfbCnt, + Word16 grpSfb, + Word16 maxSfb, + Word16 msDigest, + Word16 *jsFlags, + HANDLE_BIT_BUF hBitStream) +{ + Word16 sfb, sfbOff; + + + switch(msDigest) + { + case MS_NONE: + WriteBits(hBitStream,SI_MS_MASK_NONE,2); + break; + + case MS_ALL: + WriteBits(hBitStream,SI_MS_MASK_ALL,2); + break; + + case MS_SOME: + WriteBits(hBitStream,SI_MS_MASK_SOME,2); + for(sfbOff = 0; sfbOff < sfbCnt; sfbOff+=grpSfb) { + for(sfb=0; sfb<maxSfb; sfb++) { + + if(jsFlags[sfbOff+sfb] & MS_ON) { + WriteBits(hBitStream,1,1); + } + else{ + WriteBits(hBitStream,0,1); + } + } + } + break; + } + +} + +/***************************************************************************** +* +* function name: encodeTnsData +* description: encode TNS data (filter order, coeffs, ..) +* returns: none +* +*****************************************************************************/ +static void encodeTnsData(TNS_INFO tnsInfo, + Word16 blockType, + HANDLE_BIT_BUF hBitStream) { + Word16 i,k; + Flag tnsPresent; + Word16 numOfWindows; + Word16 coefBits; + Flag isShort; + + + if (blockType==2) { + isShort = 1; + numOfWindows = TRANS_FAC; + } + else { + isShort = 0; + numOfWindows = 1; + } + + tnsPresent=0; + for (i=0; i<numOfWindows; i++) { + + if (tnsInfo.tnsActive[i]) { + tnsPresent=1; + } + } + + if (tnsPresent==0) { + WriteBits(hBitStream,0,1); + } + else{ /* there is data to be written*/ + WriteBits(hBitStream,1,1); /*data_present */ + for (i=0; i<numOfWindows; i++) { + + WriteBits(hBitStream,tnsInfo.tnsActive[i],(isShort?1:2)); + + if (tnsInfo.tnsActive[i]) { + + WriteBits(hBitStream,((tnsInfo.coefRes[i] - 4)==0?1:0),1); + + WriteBits(hBitStream,tnsInfo.length[i],(isShort?4:6)); + + WriteBits(hBitStream,tnsInfo.order[i],(isShort?3:5)); + + if (tnsInfo.order[i]){ + WriteBits(hBitStream, FILTER_DIRECTION, 1); + + if(tnsInfo.coefRes[i] == 4) { + coefBits = 3; + for(k=0; k<tnsInfo.order[i]; k++) { + + if (tnsInfo.coef[i*TNS_MAX_ORDER_SHORT+k] > 3 || + tnsInfo.coef[i*TNS_MAX_ORDER_SHORT+k] < -4) { + coefBits = 4; + break; + } + } + } + else { + coefBits = 2; + for(k=0; k<tnsInfo.order[i]; k++) { + + if (tnsInfo.coef[i*TNS_MAX_ORDER_SHORT+k] > 1 || + tnsInfo.coef[i*TNS_MAX_ORDER_SHORT+k] < -2) { + coefBits = 3; + break; + } + } + } + WriteBits(hBitStream, tnsInfo.coefRes[i] - coefBits, 1); /*coef_compres*/ + for (k=0; k<tnsInfo.order[i]; k++ ) { + static const Word16 rmask[] = {0,1,3,7,15}; + + WriteBits(hBitStream,tnsInfo.coef[i*TNS_MAX_ORDER_SHORT+k] & rmask[coefBits],coefBits); + } + } + } + } + } + +} + +/***************************************************************************** +* +* function name: encodeGainControlData +* description: unsupported +* returns: none +* +*****************************************************************************/ +static void encodeGainControlData(HANDLE_BIT_BUF hBitStream) +{ + WriteBits(hBitStream,0,1); +} + +/***************************************************************************** +* +* function name: encodePulseData +* description: not supported yet (dummy) +* returns: none +* +*****************************************************************************/ +static void encodePulseData(HANDLE_BIT_BUF hBitStream) +{ + WriteBits(hBitStream,0,1); +} + + +/***************************************************************************** +* +* function name: WriteIndividualChannelStream +* description: management of write process of individual channel stream +* returns: none +* +*****************************************************************************/ +static void +writeIndividualChannelStream(Flag commonWindow, + Word16 mdctScale, + Word16 windowShape, + Word16 groupingMask, + Word16 *sfbOffset, + Word16 scf[], + UWord16 *maxValueInSfb, + Word16 globalGain, + Word16 quantSpec[], + SECTION_DATA *sectionData, + HANDLE_BIT_BUF hBitStream, + TNS_INFO tnsInfo) +{ + Word16 logNorm; + + logNorm = LOG_NORM_PCM - (mdctScale + 1); + + encodeGlobalGain(globalGain, logNorm,scf[sectionData->firstScf], hBitStream); + + + if(!commonWindow) { + encodeIcsInfo(sectionData->blockType, windowShape, groupingMask, sectionData, hBitStream); + } + + encodeSectionData(sectionData, hBitStream); + + encodeScaleFactorData(maxValueInSfb, + sectionData, + scf, + hBitStream); + + encodePulseData(hBitStream); + + encodeTnsData(tnsInfo, sectionData->blockType, hBitStream); + + encodeGainControlData(hBitStream); + + encodeSpectralData(sfbOffset, + sectionData, + quantSpec, + hBitStream); + +} + +/***************************************************************************** +* +* function name: writeSingleChannelElement +* description: write single channel element to bitstream +* returns: none +* +*****************************************************************************/ +static Word16 writeSingleChannelElement(Word16 instanceTag, + Word16 *sfbOffset, + QC_OUT_CHANNEL* qcOutChannel, + HANDLE_BIT_BUF hBitStream, + TNS_INFO tnsInfo) +{ + WriteBits(hBitStream,ID_SCE,3); + WriteBits(hBitStream,instanceTag,4); + writeIndividualChannelStream(0, + qcOutChannel->mdctScale, + qcOutChannel->windowShape, + qcOutChannel->groupingMask, + sfbOffset, + qcOutChannel->scf, + qcOutChannel->maxValueInSfb, + qcOutChannel->globalGain, + qcOutChannel->quantSpec, + &(qcOutChannel->sectionData), + hBitStream, + tnsInfo + ); + return(0); +} + + + +/***************************************************************************** +* +* function name: writeChannelPairElement +* description: +* returns: none +* +*****************************************************************************/ +static Word16 writeChannelPairElement(Word16 instanceTag, + Word16 msDigest, + Word16 msFlags[MAX_GROUPED_SFB], + Word16 *sfbOffset[2], + QC_OUT_CHANNEL qcOutChannel[2], + HANDLE_BIT_BUF hBitStream, + TNS_INFO tnsInfo[2]) +{ + WriteBits(hBitStream,ID_CPE,3); + WriteBits(hBitStream,instanceTag,4); + WriteBits(hBitStream,1,1); /* common window */ + + encodeIcsInfo(qcOutChannel[0].sectionData.blockType, + qcOutChannel[0].windowShape, + qcOutChannel[0].groupingMask, + &(qcOutChannel[0].sectionData), + hBitStream); + + encodeMSInfo(qcOutChannel[0].sectionData.sfbCnt, + qcOutChannel[0].sectionData.sfbPerGroup, + qcOutChannel[0].sectionData.maxSfbPerGroup, + msDigest, + msFlags, + hBitStream); + + writeIndividualChannelStream(1, + qcOutChannel[0].mdctScale, + qcOutChannel[0].windowShape, + qcOutChannel[0].groupingMask, + sfbOffset[0], + qcOutChannel[0].scf, + qcOutChannel[0].maxValueInSfb, + qcOutChannel[0].globalGain, + qcOutChannel[0].quantSpec, + &(qcOutChannel[0].sectionData), + hBitStream, + tnsInfo[0]); + + writeIndividualChannelStream(1, + qcOutChannel[1].mdctScale, + qcOutChannel[1].windowShape, + qcOutChannel[1].groupingMask, + sfbOffset[1], + qcOutChannel[1].scf, + qcOutChannel[1].maxValueInSfb, + qcOutChannel[1].globalGain, + qcOutChannel[1].quantSpec, + &(qcOutChannel[1].sectionData), + hBitStream, + tnsInfo[1]); + + return(0); +} + + + +/***************************************************************************** +* +* function name: writeFillElement +* description: write fill elements to bitstream +* returns: none +* +*****************************************************************************/ +static void writeFillElement( const UWord8 *ancBytes, + Word16 totFillBits, + HANDLE_BIT_BUF hBitStream) +{ + Word16 i; + Word16 cnt,esc_count; + + /* + Write fill Element(s): + amount of a fill element can be 7+X*8 Bits, X element of [0..270] + */ + + while(totFillBits >= (3+4)) { + cnt = min(((totFillBits - (3+4)) >> 3), ((1<<4)-1)); + + WriteBits(hBitStream,ID_FIL,3); + WriteBits(hBitStream,cnt,4); + + totFillBits = totFillBits - (3+4); + + + if ((cnt == (1<<4)-1)) { + + esc_count = min( ((totFillBits >> 3) - ((1<<4)-1)), (1<<8)-1); + WriteBits(hBitStream,esc_count,8); + totFillBits = (totFillBits - 8); + cnt = cnt + (esc_count - 1); + } + + for(i=0;i<cnt;i++) { + + if(ancBytes) + WriteBits(hBitStream, *ancBytes++,8); + else + WriteBits(hBitStream,0,8); + totFillBits = totFillBits - 8; + } + } +} +
+/***************************************************************************** +* +* function name: WriteBitStream +* description: main function of write bitsteam process +* returns: 0 if success +* +*****************************************************************************/ +Word16 WriteBitstream (HANDLE_BIT_BUF hBitStream, + ELEMENT_INFO elInfo, + QC_OUT *qcOut, + PSY_OUT *psyOut, + Word16 *globUsedBits, + const UWord8 *ancBytes,
+ Word16 sampindex + ) /* returns error code */ +{ + Word16 bitMarkUp; + Word16 elementUsedBits; + Word16 frameBits=0;
+
+ /* struct bitbuffer bsWriteCopy; */
+ bitMarkUp = GetBitsAvail(hBitStream);
+ if(qcOut->qcElement.adtsUsed) /* write adts header*/
+ {
+ WriteBits(hBitStream, 0xFFF, 12); /* 12 bit Syncword */
+ WriteBits(hBitStream, 1, 1); /* ID == 0 for MPEG4 AAC, 1 for MPEG2 AAC */
+ WriteBits(hBitStream, 0, 2); /* layer == 0 */
+ WriteBits(hBitStream, 1, 1); /* protection absent */
+ WriteBits(hBitStream, 1, 2); /* profile */
+ WriteBits(hBitStream, sampindex, 4); /* sampling rate */
+ WriteBits(hBitStream, 0, 1); /* private bit */
+ WriteBits(hBitStream, elInfo.nChannelsInEl, 3); /* ch. config (must be > 0) */
+ /* simply using numChannels only works for
+ 6 channels or less, else a channel
+ configuration should be written */
+ WriteBits(hBitStream, 0, 1); /* original/copy */
+ WriteBits(hBitStream, 0, 1); /* home */
+
+ /* Variable ADTS header */
+ WriteBits(hBitStream, 0, 1); /* copyr. id. bit */
+ WriteBits(hBitStream, 0, 1); /* copyr. id. start */
+ WriteBits(hBitStream, *globUsedBits >> 3, 13);
+ WriteBits(hBitStream, 0x7FF, 11); /* buffer fullness (0x7FF for VBR) */
+ WriteBits(hBitStream, 0, 2); /* raw data blocks (0+1=1) */
+ }
+ + *globUsedBits=0; + + { + + Word16 *sfbOffset[2]; + TNS_INFO tnsInfo[2]; + elementUsedBits = 0; + + switch (elInfo.elType) { + + case ID_SCE: /* single channel */ + sfbOffset[0] = psyOut->psyOutChannel[elInfo.ChannelIndex[0]].sfbOffsets; + tnsInfo[0] = psyOut->psyOutChannel[elInfo.ChannelIndex[0]].tnsInfo; + + writeSingleChannelElement(elInfo.instanceTag, + sfbOffset[0], + &qcOut->qcChannel[elInfo.ChannelIndex[0]], + hBitStream, + tnsInfo[0]); + break; + + case ID_CPE: /* channel pair */ + { + Word16 msDigest; + Word16 *msFlags = psyOut->psyOutElement.toolsInfo.msMask; + msDigest = psyOut->psyOutElement.toolsInfo.msDigest; + sfbOffset[0] = + psyOut->psyOutChannel[elInfo.ChannelIndex[0]].sfbOffsets; + sfbOffset[1] = + psyOut->psyOutChannel[elInfo.ChannelIndex[1]].sfbOffsets; + + tnsInfo[0]= + psyOut->psyOutChannel[elInfo.ChannelIndex[0]].tnsInfo; + tnsInfo[1]= + psyOut->psyOutChannel[elInfo.ChannelIndex[1]].tnsInfo; + writeChannelPairElement(elInfo.instanceTag, + msDigest, + msFlags, + sfbOffset, + &qcOut->qcChannel[elInfo.ChannelIndex[0]], + hBitStream, + tnsInfo); + } + break; + + default: + return(1); + + } /* switch */ + + elementUsedBits = elementUsedBits - bitMarkUp; + bitMarkUp = GetBitsAvail(hBitStream); + frameBits = frameBits + elementUsedBits + bitMarkUp; + + } + + writeFillElement(NULL, + qcOut->totFillBits, + hBitStream); + + WriteBits(hBitStream,ID_END,3); + + /* byte alignement */ + WriteBits(hBitStream,0, (8 - (hBitStream->cntBits & 7)) & 7); + + *globUsedBits = *globUsedBits- bitMarkUp; + bitMarkUp = GetBitsAvail(hBitStream); + *globUsedBits = *globUsedBits + bitMarkUp; + frameBits = frameBits + *globUsedBits; + + + if (frameBits != (qcOut->totStaticBitsUsed+qcOut->totDynBitsUsed + qcOut->totAncBitsUsed + + qcOut->totFillBits + qcOut->alignBits)) { + return(-1); + } + return(0); +} |