summaryrefslogtreecommitdiffstats
path: root/media/libstagefright/codecs/aacenc/src/dyn_bits.c
diff options
context:
space:
mode:
Diffstat (limited to 'media/libstagefright/codecs/aacenc/src/dyn_bits.c')
-rw-r--r--media/libstagefright/codecs/aacenc/src/dyn_bits.c545
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);
+}
+