diff options
Diffstat (limited to 'media/libstagefright/codecs/aacenc/src/dyn_bits.c')
-rw-r--r-- | media/libstagefright/codecs/aacenc/src/dyn_bits.c | 545 |
1 files changed, 545 insertions, 0 deletions
diff --git a/media/libstagefright/codecs/aacenc/src/dyn_bits.c b/media/libstagefright/codecs/aacenc/src/dyn_bits.c new file mode 100644 index 0000000..3deacca --- /dev/null +++ b/media/libstagefright/codecs/aacenc/src/dyn_bits.c @@ -0,0 +1,545 @@ +/*
+ ** 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: dyn_bits.c
+
+ Content: Noiseless coder module functions
+
+*******************************************************************************/ + +#include "aac_rom.h" +#include "dyn_bits.h" +#include "bit_cnt.h" +#include "psy_const.h" + + +/***************************************************************************** +* +* function name: buildBitLookUp +* description: count bits using all possible tables +* +*****************************************************************************/ +static void +buildBitLookUp(const Word16 *quantSpectrum, + const Word16 maxSfb, + const Word16 *sfbOffset, + const UWord16 *sfbMax, + Word16 bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1], + SECTION_INFO * sectionInfo) +{ + Word32 i; + + for (i=0; i<maxSfb; i++) { + Word16 sfbWidth, maxVal; + + sectionInfo[i].sfbCnt = 1; + sectionInfo[i].sfbStart = i; + sectionInfo[i].sectionBits = INVALID_BITCOUNT; + sectionInfo[i].codeBook = -1; + sfbWidth = sfbOffset[i + 1] - sfbOffset[i]; + maxVal = sfbMax[i]; + bitCount(quantSpectrum + sfbOffset[i], sfbWidth, maxVal, bitLookUp[i]); + } +} + + +/***************************************************************************** +* +* function name: findBestBook +* description: essential helper functions +* +*****************************************************************************/ +static Word16 +findBestBook(const Word16 *bc, Word16 *book) +{ + Word32 minBits, j; + minBits = INVALID_BITCOUNT; + + for (j=0; j<=CODE_BOOK_ESC_NDX; j++) { + + if (bc[j] < minBits) { + minBits = bc[j]; + *book = j; + } + } + return extract_l(minBits); +} + +static Word16 +findMinMergeBits(const Word16 *bc1, const Word16 *bc2) +{ + Word32 minBits, j, sum; + minBits = INVALID_BITCOUNT; + + for (j=0; j<=CODE_BOOK_ESC_NDX; j++) { + sum = bc1[j] + bc2[j]; + if (sum < minBits) { + minBits = sum; + } + } + return extract_l(minBits); +} + +static void +mergeBitLookUp(Word16 *bc1, const Word16 *bc2) +{ + Word32 j; + + for (j=0; j<=CODE_BOOK_ESC_NDX; j++) { + bc1[j] = min(bc1[j] + bc2[j], INVALID_BITCOUNT); + } +} + +static Word16 +findMaxMerge(const Word16 mergeGainLookUp[MAX_SFB_LONG], + const SECTION_INFO *sectionInfo, + const Word16 maxSfb, Word16 *maxNdx) +{ + Word32 i, maxMergeGain; + maxMergeGain = 0; + + for (i=0; i+sectionInfo[i].sfbCnt < maxSfb; i += sectionInfo[i].sfbCnt) { + + if (mergeGainLookUp[i] > maxMergeGain) { + maxMergeGain = mergeGainLookUp[i]; + *maxNdx = i; + } + } + return extract_l(maxMergeGain); +} + + + +static Word16 +CalcMergeGain(const SECTION_INFO *sectionInfo, + Word16 bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1], + const Word16 *sideInfoTab, + const Word16 ndx1, + const Word16 ndx2) +{ + Word32 SplitBits; + Word32 MergeBits; + Word32 MergeGain; + + /* + Bit amount for splitted sections + */ + SplitBits = sectionInfo[ndx1].sectionBits + sectionInfo[ndx2].sectionBits; + + MergeBits = sideInfoTab[sectionInfo[ndx1].sfbCnt + sectionInfo[ndx2].sfbCnt] + + findMinMergeBits(bitLookUp[ndx1], bitLookUp[ndx2]); + MergeGain = (SplitBits - MergeBits); + + return extract_l(MergeGain); +} + +/* + sectioning Stage 0:find minimum codbooks +*/ + +static void +gmStage0(SECTION_INFO * sectionInfo, + Word16 bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1], + const Word16 maxSfb) +{ + Word32 i; + + for (i=0; i<maxSfb; i++) { + /* Side-Info bits will be calculated in Stage 1! */ + + if (sectionInfo[i].sectionBits == INVALID_BITCOUNT) { + sectionInfo[i].sectionBits = findBestBook(bitLookUp[i], &(sectionInfo[i].codeBook)); + } + } +} + +/* + sectioning Stage 1:merge all connected regions with the same code book and + calculate side info +*/ + +static void +gmStage1(SECTION_INFO * sectionInfo, + Word16 bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1], + const Word16 maxSfb, + const Word16 *sideInfoTab) +{ + SECTION_INFO * sectionInfo_s;
+ SECTION_INFO * sectionInfo_e;
+ Word32 mergeStart, mergeEnd; + mergeStart = 0; + + do { + + sectionInfo_s = sectionInfo + mergeStart;
+ for (mergeEnd=mergeStart+1; mergeEnd<maxSfb; mergeEnd++) { + sectionInfo_e = sectionInfo + mergeEnd; + if (sectionInfo_s->codeBook != sectionInfo_e->codeBook) + break; + sectionInfo_s->sfbCnt += 1; + sectionInfo_s->sectionBits += sectionInfo_e->sectionBits; + + mergeBitLookUp(bitLookUp[mergeStart], bitLookUp[mergeEnd]); + } + + sectionInfo_s->sectionBits += sideInfoTab[sectionInfo_s->sfbCnt]; + sectionInfo[mergeEnd - 1].sfbStart = sectionInfo_s->sfbStart; /* speed up prev search */ + + mergeStart = mergeEnd; + + + } while (mergeStart - maxSfb < 0); +} + +/* + sectioning Stage 2:greedy merge algorithm, merge connected sections with + maximum bit gain until no more gain is possible +*/ +static void +gmStage2(SECTION_INFO *sectionInfo, + Word16 mergeGainLookUp[MAX_SFB_LONG], + Word16 bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1], + const Word16 maxSfb, + const Word16 *sideInfoTab) +{ + Word16 i; + + for (i=0; i+sectionInfo[i].sfbCnt<maxSfb; i+=sectionInfo[i].sfbCnt) { + mergeGainLookUp[i] = CalcMergeGain(sectionInfo, + bitLookUp, + sideInfoTab, + i, + (i + sectionInfo[i].sfbCnt)); + } + + while (TRUE) { + Word16 maxMergeGain, maxNdx, maxNdxNext, maxNdxLast; + + maxMergeGain = findMaxMerge(mergeGainLookUp, sectionInfo, maxSfb, &maxNdx); + + + if (maxMergeGain <= 0) + break; + + + maxNdxNext = maxNdx + sectionInfo[maxNdx].sfbCnt; + + sectionInfo[maxNdx].sfbCnt = sectionInfo[maxNdx].sfbCnt + sectionInfo[maxNdxNext].sfbCnt; + sectionInfo[maxNdx].sectionBits = sectionInfo[maxNdx].sectionBits + + (sectionInfo[maxNdxNext].sectionBits - maxMergeGain); + + + mergeBitLookUp(bitLookUp[maxNdx], bitLookUp[maxNdxNext]); + + + if (maxNdx != 0) { + maxNdxLast = sectionInfo[maxNdx - 1].sfbStart; + mergeGainLookUp[maxNdxLast] = CalcMergeGain(sectionInfo, + bitLookUp, + sideInfoTab, + maxNdxLast, + maxNdx); + } + maxNdxNext = maxNdx + sectionInfo[maxNdx].sfbCnt; + + sectionInfo[maxNdxNext - 1].sfbStart = sectionInfo[maxNdx].sfbStart; + + + if (maxNdxNext - maxSfb < 0) { + mergeGainLookUp[maxNdx] = CalcMergeGain(sectionInfo, + bitLookUp, + sideInfoTab, + maxNdx, + maxNdxNext); + } + } +} + +/* + count bits used by the noiseless coder +*/ +static void +noiselessCounter(SECTION_DATA *sectionData, + Word16 mergeGainLookUp[MAX_SFB_LONG], + Word16 bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1], + const Word16 *quantSpectrum, + const UWord16 *maxValueInSfb, + const Word16 *sfbOffset, + const Word32 blockType) +{ + Word32 grpNdx, i; + Word16 *sideInfoTab = NULL; + SECTION_INFO *sectionInfo; + + /* + use appropriate side info table + */ + switch (blockType) + { + case LONG_WINDOW: + case START_WINDOW: + case STOP_WINDOW: + sideInfoTab = sideInfoTabLong; + break; + case SHORT_WINDOW: + sideInfoTab = sideInfoTabShort; + break; + } + + + sectionData->noOfSections = 0; + sectionData->huffmanBits = 0; + sectionData->sideInfoBits = 0; + + + if (sectionData->maxSfbPerGroup == 0) + return; + + /* + loop trough groups + */ + for (grpNdx=0; grpNdx<sectionData->sfbCnt; grpNdx+=sectionData->sfbPerGroup) { + + sectionInfo = sectionData->sectionInfo + sectionData->noOfSections; + + buildBitLookUp(quantSpectrum, + sectionData->maxSfbPerGroup, + sfbOffset + grpNdx, + maxValueInSfb + grpNdx, + bitLookUp, + sectionInfo); + + /* + 0.Stage + */ + gmStage0(sectionInfo, bitLookUp, sectionData->maxSfbPerGroup); + + /* + 1.Stage + */ + gmStage1(sectionInfo, bitLookUp, sectionData->maxSfbPerGroup, sideInfoTab); + + + /* + 2.Stage + */ + gmStage2(sectionInfo, + mergeGainLookUp, + bitLookUp, + sectionData->maxSfbPerGroup, + sideInfoTab); + + + /* + compress output, calculate total huff and side bits + */ + for (i=0; i<sectionData->maxSfbPerGroup; i+=sectionInfo[i].sfbCnt) { + findBestBook(bitLookUp[i], &(sectionInfo[i].codeBook)); + sectionInfo[i].sfbStart = sectionInfo[i].sfbStart + grpNdx; + + sectionData->huffmanBits = (sectionData->huffmanBits + + (sectionInfo[i].sectionBits - sideInfoTab[sectionInfo[i].sfbCnt])); + sectionData->sideInfoBits = (sectionData->sideInfoBits + sideInfoTab[sectionInfo[i].sfbCnt]); + sectionData->sectionInfo[sectionData->noOfSections] = sectionInfo[i]; + sectionData->noOfSections = sectionData->noOfSections + 1; + } + } +} + + +/******************************************************************************* +* +* functionname: scfCount +* returns : --- +* description : count bits used by scalefactors. +* +********************************************************************************/ +static void scfCount(const Word16 *scalefacGain, + const UWord16 *maxValueInSfb, + SECTION_DATA * sectionData) + +{ + SECTION_INFO *psectionInfo;
+ SECTION_INFO *psectionInfom;
+
+ /* counter */ + Word32 i = 0; /* section counter */ + Word32 j = 0; /* sfb counter */ + Word32 k = 0; /* current section auxiliary counter */ + Word32 m = 0; /* other section auxiliary counter */ + Word32 n = 0; /* other sfb auxiliary counter */ + + /* further variables */ + Word32 lastValScf = 0; + Word32 deltaScf = 0; + Flag found = 0; + Word32 scfSkipCounter = 0; + + + sectionData->scalefacBits = 0; + + + if (scalefacGain == NULL) { + return; + } + + lastValScf = 0; + sectionData->firstScf = 0;
+ + psectionInfo = sectionData->sectionInfo; + for (i=0; i<sectionData->noOfSections; i++) { + + if (psectionInfo->codeBook != CODE_BOOK_ZERO_NO) { + sectionData->firstScf = psectionInfo->sfbStart; + lastValScf = scalefacGain[sectionData->firstScf]; + break; + }
+ psectionInfo += 1; + }
+ + psectionInfo = sectionData->sectionInfo; + for (i=0; i<sectionData->noOfSections; i++, psectionInfo += 1) { + + if (psectionInfo->codeBook != CODE_BOOK_ZERO_NO + && psectionInfo->codeBook != CODE_BOOK_PNS_NO) { + for (j = psectionInfo->sfbStart; + j < (psectionInfo->sfbStart + psectionInfo->sfbCnt); j++) { + /* check if we can repeat the last value to save bits */ + + if (maxValueInSfb[j] == 0) { + found = 0; + + if (scfSkipCounter == 0) { + /* end of section */ + + if (j - ((psectionInfo->sfbStart + psectionInfo->sfbCnt) - 1) == 0) { + found = 0; + } + else { + for (k = j + 1; k < psectionInfo->sfbStart + psectionInfo->sfbCnt; k++) { + + if (maxValueInSfb[k] != 0) { + int tmp = L_abs(scalefacGain[k] - lastValScf); + found = 1; + + if ( tmp < CODE_BOOK_SCF_LAV) { + /* save bits */ + deltaScf = 0; + } + else { + /* do not save bits */ + deltaScf = lastValScf - scalefacGain[j]; + lastValScf = scalefacGain[j]; + scfSkipCounter = 0; + } + break; + } + /* count scalefactor skip */ + scfSkipCounter = scfSkipCounter + 1; + } + } +
+ psectionInfom = psectionInfo + 1; + /* search for the next maxValueInSfb[] != 0 in all other sections */ + for (m = i + 1; (m < sectionData->noOfSections) && (found == 0); m++) { + + if ((psectionInfom->codeBook != CODE_BOOK_ZERO_NO) && + (psectionInfom->codeBook != CODE_BOOK_PNS_NO)) { + for (n = psectionInfom->sfbStart; + n < (psectionInfom->sfbStart + psectionInfom->sfbCnt); n++) { + + if (maxValueInSfb[n] != 0) { + found = 1; + + if ( (abs_s(scalefacGain[n] - lastValScf) < CODE_BOOK_SCF_LAV)) { + deltaScf = 0; + } + else { + deltaScf = (lastValScf - scalefacGain[j]); + lastValScf = scalefacGain[j]; + scfSkipCounter = 0; + } + break; + } + /* count scalefactor skip */ + scfSkipCounter = scfSkipCounter + 1; + } + }
+
+ psectionInfom += 1; + } + + if (found == 0) { + deltaScf = 0; + scfSkipCounter = 0; + } + } + else { + deltaScf = 0; + scfSkipCounter = scfSkipCounter - 1; + }
+ } + else { + deltaScf = lastValScf - scalefacGain[j]; + lastValScf = scalefacGain[j]; + } + sectionData->scalefacBits += bitCountScalefactorDelta(deltaScf); + } + } + } +} + + +typedef Word16 (*lookUpTable)[CODE_BOOK_ESC_NDX + 1]; + + +Word16 +dynBitCount(const Word16 *quantSpectrum, + const UWord16 *maxValueInSfb, + const Word16 *scalefac, + const Word16 blockType, + const Word16 sfbCnt, + const Word16 maxSfbPerGroup, + const Word16 sfbPerGroup, + const Word16 *sfbOffset, + SECTION_DATA *sectionData) +{ + sectionData->blockType = blockType; + sectionData->sfbCnt = sfbCnt; + sectionData->sfbPerGroup = sfbPerGroup; + if(sfbPerGroup) + sectionData->noOfGroups = sfbCnt/sfbPerGroup; + else + sectionData->noOfGroups = 0x7fff; + sectionData->maxSfbPerGroup = maxSfbPerGroup; + + noiselessCounter(sectionData, + sectionData->mergeGainLookUp, + (lookUpTable)sectionData->bitLookUp, + quantSpectrum, + maxValueInSfb, + sfbOffset, + blockType); + + scfCount(scalefac, + maxValueInSfb, + sectionData); + + + return (sectionData->huffmanBits + sectionData->sideInfoBits +
+ sectionData->scalefacBits); +} + |