diff options
author | Matthias P. Braendli <matthias.braendli@mpb.li> | 2019-11-11 11:38:02 +0100 |
---|---|---|
committer | Matthias P. Braendli <matthias.braendli@mpb.li> | 2019-11-11 11:38:02 +0100 |
commit | 0e5af65c467b2423a0b857ae3ad98c91acc1e190 (patch) | |
tree | d07f69550d8886271e44fe79c4dcfb299cafbd38 /fdk-aac/libSBRenc/src/ps_bitenc.cpp | |
parent | efe406d9724f959c8bc2a31802559ca6d41fd897 (diff) | |
download | ODR-AudioEnc-0e5af65c467b2423a0b857ae3ad98c91acc1e190.tar.gz ODR-AudioEnc-0e5af65c467b2423a0b857ae3ad98c91acc1e190.tar.bz2 ODR-AudioEnc-0e5af65c467b2423a0b857ae3ad98c91acc1e190.zip |
Include patched FDK-AAC in the repository
The initial idea was to get the DAB+ patch into upstream, but since
that follows the android source releases, there is no place for a custom
DAB+ patch there.
So instead of having to maintain a patched fdk-aac that has to have the
same .so version as the distribution package on which it is installed,
we prefer having a separate fdk-aac-dab library to avoid collision.
At that point, there's no reason to keep fdk-aac in a separate
repository, as odr-audioenc is the only tool that needs DAB+ encoding
support. Including it here simplifies installation, and makes it
consistent with toolame-dab, also shipped in this repository.
DAB+ decoding support (needed by ODR-SourceCompanion, dablin, etisnoop,
welle.io and others) can be done using upstream FDK-AAC.
Diffstat (limited to 'fdk-aac/libSBRenc/src/ps_bitenc.cpp')
-rw-r--r-- | fdk-aac/libSBRenc/src/ps_bitenc.cpp | 624 |
1 files changed, 624 insertions, 0 deletions
diff --git a/fdk-aac/libSBRenc/src/ps_bitenc.cpp b/fdk-aac/libSBRenc/src/ps_bitenc.cpp new file mode 100644 index 0000000..e30af2a --- /dev/null +++ b/fdk-aac/libSBRenc/src/ps_bitenc.cpp @@ -0,0 +1,624 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): N. Rettelbach + + Description: Parametric Stereo bitstream encoder + +*******************************************************************************/ + +#include "ps_bitenc.h" + +#include "ps_main.h" + +static inline UCHAR FDKsbrEnc_WriteBits_ps(HANDLE_FDK_BITSTREAM hBitStream, + UINT value, + const UINT numberOfBits) { + /* hBitStream == NULL happens here intentionally */ + if (hBitStream != NULL) { + FDKwriteBits(hBitStream, value, numberOfBits); + } + return numberOfBits; +} + +#define SI_SBR_EXTENSION_SIZE_BITS 4 +#define SI_SBR_EXTENSION_ESC_COUNT_BITS 8 +#define SI_SBR_EXTENSION_ID_BITS 2 +#define EXTENSION_ID_PS_CODING 2 +#define PS_EXT_ID_V0 0 + +static const INT iidDeltaCoarse_Offset = 14; +static const INT iidDeltaCoarse_MaxVal = 28; +static const INT iidDeltaFine_Offset = 30; +static const INT iidDeltaFine_MaxVal = 60; + +/* PS Stereo Huffmantable: iidDeltaFreqCoarse */ +static const UINT iidDeltaFreqCoarse_Length[] = { + 17, 17, 17, 17, 16, 15, 13, 10, 9, 7, 6, 5, 4, 3, 1, + 3, 4, 5, 6, 6, 8, 11, 13, 14, 14, 15, 17, 18, 18}; +static const UINT iidDeltaFreqCoarse_Code[] = { + 0x0001fffb, 0x0001fffc, 0x0001fffd, 0x0001fffa, 0x0000fffc, 0x00007ffc, + 0x00001ffd, 0x000003fe, 0x000001fe, 0x0000007e, 0x0000003c, 0x0000001d, + 0x0000000d, 0x00000005, 0000000000, 0x00000004, 0x0000000c, 0x0000001c, + 0x0000003d, 0x0000003e, 0x000000fe, 0x000007fe, 0x00001ffc, 0x00003ffc, + 0x00003ffd, 0x00007ffd, 0x0001fffe, 0x0003fffe, 0x0003ffff}; + +/* PS Stereo Huffmantable: iidDeltaFreqFine */ +static const UINT iidDeltaFreqFine_Length[] = { + 18, 18, 18, 18, 18, 18, 18, 18, 18, 17, 18, 17, 17, 16, 16, 15, + 14, 14, 13, 12, 12, 11, 10, 10, 8, 7, 6, 5, 4, 3, 1, 3, + 4, 5, 6, 7, 8, 9, 10, 11, 11, 12, 13, 14, 14, 15, 16, 16, + 17, 17, 18, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18}; +static const UINT iidDeltaFreqFine_Code[] = { + 0x0001feb4, 0x0001feb5, 0x0001fd76, 0x0001fd77, 0x0001fd74, 0x0001fd75, + 0x0001fe8a, 0x0001fe8b, 0x0001fe88, 0x0000fe80, 0x0001feb6, 0x0000fe82, + 0x0000feb8, 0x00007f42, 0x00007fae, 0x00003faf, 0x00001fd1, 0x00001fe9, + 0x00000fe9, 0x000007ea, 0x000007fb, 0x000003fb, 0x000001fb, 0x000001ff, + 0x0000007c, 0x0000003c, 0x0000001c, 0x0000000c, 0000000000, 0x00000001, + 0x00000001, 0x00000002, 0x00000001, 0x0000000d, 0x0000001d, 0x0000003d, + 0x0000007d, 0x000000fc, 0x000001fc, 0x000003fc, 0x000003f4, 0x000007eb, + 0x00000fea, 0x00001fea, 0x00001fd6, 0x00003fd0, 0x00007faf, 0x00007f43, + 0x0000feb9, 0x0000fe83, 0x0001feb7, 0x0000fe81, 0x0001fe89, 0x0001fe8e, + 0x0001fe8f, 0x0001fe8c, 0x0001fe8d, 0x0001feb2, 0x0001feb3, 0x0001feb0, + 0x0001feb1}; + +/* PS Stereo Huffmantable: iidDeltaTimeCoarse */ +static const UINT iidDeltaTimeCoarse_Length[] = { + 19, 19, 19, 20, 20, 20, 17, 15, 12, 10, 8, 6, 4, 2, 1, + 3, 5, 7, 9, 11, 13, 14, 17, 19, 20, 20, 20, 20, 20}; +static const UINT iidDeltaTimeCoarse_Code[] = { + 0x0007fff9, 0x0007fffa, 0x0007fffb, 0x000ffff8, 0x000ffff9, 0x000ffffa, + 0x0001fffd, 0x00007ffe, 0x00000ffe, 0x000003fe, 0x000000fe, 0x0000003e, + 0x0000000e, 0x00000002, 0000000000, 0x00000006, 0x0000001e, 0x0000007e, + 0x000001fe, 0x000007fe, 0x00001ffe, 0x00003ffe, 0x0001fffc, 0x0007fff8, + 0x000ffffb, 0x000ffffc, 0x000ffffd, 0x000ffffe, 0x000fffff}; + +/* PS Stereo Huffmantable: iidDeltaTimeFine */ +static const UINT iidDeltaTimeFine_Length[] = { + 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, + 14, 13, 13, 13, 12, 12, 11, 10, 9, 9, 7, 6, 5, 3, 1, 2, + 5, 6, 7, 8, 9, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, + 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}; +static const UINT iidDeltaTimeFine_Code[] = { + 0x00004ed4, 0x00004ed5, 0x00004ece, 0x00004ecf, 0x00004ecc, 0x00004ed6, + 0x00004ed8, 0x00004f46, 0x00004f60, 0x00002718, 0x00002719, 0x00002764, + 0x00002765, 0x0000276d, 0x000027b1, 0x000013b7, 0x000013d6, 0x000009c7, + 0x000009e9, 0x000009ed, 0x000004ee, 0x000004f7, 0x00000278, 0x00000139, + 0x0000009a, 0x0000009f, 0x00000020, 0x00000011, 0x0000000a, 0x00000003, + 0x00000001, 0000000000, 0x0000000b, 0x00000012, 0x00000021, 0x0000004c, + 0x0000009b, 0x0000013a, 0x00000279, 0x00000270, 0x000004ef, 0x000004e2, + 0x000009ea, 0x000009d8, 0x000013d7, 0x000013d0, 0x000027b2, 0x000027a2, + 0x0000271a, 0x0000271b, 0x00004f66, 0x00004f67, 0x00004f61, 0x00004f47, + 0x00004ed9, 0x00004ed7, 0x00004ecd, 0x00004ed2, 0x00004ed3, 0x00004ed0, + 0x00004ed1}; + +static const INT iccDelta_Offset = 7; +static const INT iccDelta_MaxVal = 14; +/* PS Stereo Huffmantable: iccDeltaFreq */ +static const UINT iccDeltaFreq_Length[] = {14, 14, 12, 10, 7, 5, 3, 1, + 2, 4, 6, 8, 9, 11, 13}; +static const UINT iccDeltaFreq_Code[] = { + 0x00003fff, 0x00003ffe, 0x00000ffe, 0x000003fe, 0x0000007e, + 0x0000001e, 0x00000006, 0000000000, 0x00000002, 0x0000000e, + 0x0000003e, 0x000000fe, 0x000001fe, 0x000007fe, 0x00001ffe}; + +/* PS Stereo Huffmantable: iccDeltaTime */ +static const UINT iccDeltaTime_Length[] = {14, 13, 11, 9, 7, 5, 3, 1, + 2, 4, 6, 8, 10, 12, 14}; +static const UINT iccDeltaTime_Code[] = { + 0x00003ffe, 0x00001ffe, 0x000007fe, 0x000001fe, 0x0000007e, + 0x0000001e, 0x00000006, 0000000000, 0x00000002, 0x0000000e, + 0x0000003e, 0x000000fe, 0x000003fe, 0x00000ffe, 0x00003fff}; + +static const INT ipdDelta_Offset = 0; +static const INT ipdDelta_MaxVal = 7; +/* PS Stereo Huffmantable: ipdDeltaFreq */ +static const UINT ipdDeltaFreq_Length[] = {1, 3, 4, 4, 4, 4, 4, 4}; +static const UINT ipdDeltaFreq_Code[] = {0x00000001, 0000000000, 0x00000006, + 0x00000004, 0x00000002, 0x00000003, + 0x00000005, 0x00000007}; + +/* PS Stereo Huffmantable: ipdDeltaTime */ +static const UINT ipdDeltaTime_Length[] = {1, 3, 4, 5, 5, 4, 4, 3}; +static const UINT ipdDeltaTime_Code[] = {0x00000001, 0x00000002, 0x00000002, + 0x00000003, 0x00000002, 0000000000, + 0x00000003, 0x00000003}; + +static const INT opdDelta_Offset = 0; +static const INT opdDelta_MaxVal = 7; +/* PS Stereo Huffmantable: opdDeltaFreq */ +static const UINT opdDeltaFreq_Length[] = {1, 3, 4, 4, 5, 5, 4, 3}; +static const UINT opdDeltaFreq_Code[] = { + 0x00000001, 0x00000001, 0x00000006, 0x00000004, + 0x0000000f, 0x0000000e, 0x00000005, 0000000000, +}; + +/* PS Stereo Huffmantable: opdDeltaTime */ +static const UINT opdDeltaTime_Length[] = {1, 3, 4, 5, 5, 4, 4, 3}; +static const UINT opdDeltaTime_Code[] = {0x00000001, 0x00000002, 0x00000001, + 0x00000007, 0x00000006, 0000000000, + 0x00000002, 0x00000003}; + +static INT getNoBands(const INT mode) { + INT noBands = 0; + + switch (mode) { + case 0: + case 3: /* coarse */ + noBands = PS_BANDS_COARSE; + break; + case 1: + case 4: /* mid */ + noBands = PS_BANDS_MID; + break; + case 2: + case 5: /* fine not supported */ + default: /* coarse as default */ + noBands = PS_BANDS_COARSE; + } + + return noBands; +} + +static INT getIIDRes(INT iidMode) { + if (iidMode < 3) + return PS_IID_RES_COARSE; + else + return PS_IID_RES_FINE; +} + +static INT encodeDeltaFreq(HANDLE_FDK_BITSTREAM hBitBuf, const INT *val, + const INT nBands, const UINT *codeTable, + const UINT *lengthTable, const INT tableOffset, + const INT maxVal, INT *error) { + INT bitCnt = 0; + INT lastVal = 0; + INT band; + + for (band = 0; band < nBands; band++) { + INT delta = (val[band] - lastVal) + tableOffset; + lastVal = val[band]; + if ((delta > maxVal) || (delta < 0)) { + *error = 1; + delta = delta > 0 ? maxVal : 0; + } + bitCnt += + FDKsbrEnc_WriteBits_ps(hBitBuf, codeTable[delta], lengthTable[delta]); + } + + return bitCnt; +} + +static INT encodeDeltaTime(HANDLE_FDK_BITSTREAM hBitBuf, const INT *val, + const INT *valLast, const INT nBands, + const UINT *codeTable, const UINT *lengthTable, + const INT tableOffset, const INT maxVal, + INT *error) { + INT bitCnt = 0; + INT band; + + for (band = 0; band < nBands; band++) { + INT delta = (val[band] - valLast[band]) + tableOffset; + if ((delta > maxVal) || (delta < 0)) { + *error = 1; + delta = delta > 0 ? maxVal : 0; + } + bitCnt += + FDKsbrEnc_WriteBits_ps(hBitBuf, codeTable[delta], lengthTable[delta]); + } + + return bitCnt; +} + +INT FDKsbrEnc_EncodeIid(HANDLE_FDK_BITSTREAM hBitBuf, const INT *iidVal, + const INT *iidValLast, const INT nBands, + const PS_IID_RESOLUTION res, const PS_DELTA mode, + INT *error) { + const UINT *codeTable; + const UINT *lengthTable; + INT bitCnt = 0; + + bitCnt = 0; + + switch (mode) { + case PS_DELTA_FREQ: + switch (res) { + case PS_IID_RES_COARSE: + codeTable = iidDeltaFreqCoarse_Code; + lengthTable = iidDeltaFreqCoarse_Length; + bitCnt += encodeDeltaFreq(hBitBuf, iidVal, nBands, codeTable, + lengthTable, iidDeltaCoarse_Offset, + iidDeltaCoarse_MaxVal, error); + break; + case PS_IID_RES_FINE: + codeTable = iidDeltaFreqFine_Code; + lengthTable = iidDeltaFreqFine_Length; + bitCnt += + encodeDeltaFreq(hBitBuf, iidVal, nBands, codeTable, lengthTable, + iidDeltaFine_Offset, iidDeltaFine_MaxVal, error); + break; + default: + *error = 1; + } + break; + + case PS_DELTA_TIME: + switch (res) { + case PS_IID_RES_COARSE: + codeTable = iidDeltaTimeCoarse_Code; + lengthTable = iidDeltaTimeCoarse_Length; + bitCnt += encodeDeltaTime( + hBitBuf, iidVal, iidValLast, nBands, codeTable, lengthTable, + iidDeltaCoarse_Offset, iidDeltaCoarse_MaxVal, error); + break; + case PS_IID_RES_FINE: + codeTable = iidDeltaTimeFine_Code; + lengthTable = iidDeltaTimeFine_Length; + bitCnt += encodeDeltaTime(hBitBuf, iidVal, iidValLast, nBands, + codeTable, lengthTable, iidDeltaFine_Offset, + iidDeltaFine_MaxVal, error); + break; + default: + *error = 1; + } + break; + + default: + *error = 1; + } + + return bitCnt; +} + +INT FDKsbrEnc_EncodeIcc(HANDLE_FDK_BITSTREAM hBitBuf, const INT *iccVal, + const INT *iccValLast, const INT nBands, + const PS_DELTA mode, INT *error) { + const UINT *codeTable; + const UINT *lengthTable; + INT bitCnt = 0; + + switch (mode) { + case PS_DELTA_FREQ: + codeTable = iccDeltaFreq_Code; + lengthTable = iccDeltaFreq_Length; + bitCnt += encodeDeltaFreq(hBitBuf, iccVal, nBands, codeTable, lengthTable, + iccDelta_Offset, iccDelta_MaxVal, error); + break; + + case PS_DELTA_TIME: + codeTable = iccDeltaTime_Code; + lengthTable = iccDeltaTime_Length; + + bitCnt += + encodeDeltaTime(hBitBuf, iccVal, iccValLast, nBands, codeTable, + lengthTable, iccDelta_Offset, iccDelta_MaxVal, error); + break; + + default: + *error = 1; + } + + return bitCnt; +} + +INT FDKsbrEnc_EncodeIpd(HANDLE_FDK_BITSTREAM hBitBuf, const INT *ipdVal, + const INT *ipdValLast, const INT nBands, + const PS_DELTA mode, INT *error) { + const UINT *codeTable; + const UINT *lengthTable; + INT bitCnt = 0; + + switch (mode) { + case PS_DELTA_FREQ: + codeTable = ipdDeltaFreq_Code; + lengthTable = ipdDeltaFreq_Length; + bitCnt += encodeDeltaFreq(hBitBuf, ipdVal, nBands, codeTable, lengthTable, + ipdDelta_Offset, ipdDelta_MaxVal, error); + break; + + case PS_DELTA_TIME: + codeTable = ipdDeltaTime_Code; + lengthTable = ipdDeltaTime_Length; + + bitCnt += + encodeDeltaTime(hBitBuf, ipdVal, ipdValLast, nBands, codeTable, + lengthTable, ipdDelta_Offset, ipdDelta_MaxVal, error); + break; + + default: + *error = 1; + } + + return bitCnt; +} + +INT FDKsbrEnc_EncodeOpd(HANDLE_FDK_BITSTREAM hBitBuf, const INT *opdVal, + const INT *opdValLast, const INT nBands, + const PS_DELTA mode, INT *error) { + const UINT *codeTable; + const UINT *lengthTable; + INT bitCnt = 0; + + switch (mode) { + case PS_DELTA_FREQ: + codeTable = opdDeltaFreq_Code; + lengthTable = opdDeltaFreq_Length; + bitCnt += encodeDeltaFreq(hBitBuf, opdVal, nBands, codeTable, lengthTable, + opdDelta_Offset, opdDelta_MaxVal, error); + break; + + case PS_DELTA_TIME: + codeTable = opdDeltaTime_Code; + lengthTable = opdDeltaTime_Length; + + bitCnt += + encodeDeltaTime(hBitBuf, opdVal, opdValLast, nBands, codeTable, + lengthTable, opdDelta_Offset, opdDelta_MaxVal, error); + break; + + default: + *error = 1; + } + + return bitCnt; +} + +static INT encodeIpdOpd(HANDLE_PS_OUT psOut, HANDLE_FDK_BITSTREAM hBitBuf) { + INT bitCnt = 0; + INT error = 0; + INT env; + + FDKsbrEnc_WriteBits_ps(hBitBuf, psOut->enableIpdOpd, 1); + + if (psOut->enableIpdOpd == 1) { + INT *ipdLast = psOut->ipdLast; + INT *opdLast = psOut->opdLast; + + for (env = 0; env < psOut->nEnvelopes; env++) { + bitCnt += FDKsbrEnc_WriteBits_ps(hBitBuf, psOut->deltaIPD[env], 1); + bitCnt += FDKsbrEnc_EncodeIpd(hBitBuf, psOut->ipd[env], ipdLast, + getNoBands(psOut->iidMode), + psOut->deltaIPD[env], &error); + + bitCnt += FDKsbrEnc_WriteBits_ps(hBitBuf, psOut->deltaOPD[env], 1); + bitCnt += FDKsbrEnc_EncodeOpd(hBitBuf, psOut->opd[env], opdLast, + getNoBands(psOut->iidMode), + psOut->deltaOPD[env], &error); + } + /* reserved bit */ + bitCnt += FDKsbrEnc_WriteBits_ps(hBitBuf, 0, 1); + } + + return bitCnt; +} + +static INT getEnvIdx(const INT nEnvelopes, const INT frameClass) { + INT envIdx = 0; + + switch (nEnvelopes) { + case 0: + envIdx = 0; + break; + + case 1: + if (frameClass == 0) + envIdx = 1; + else + envIdx = 0; + break; + + case 2: + if (frameClass == 0) + envIdx = 2; + else + envIdx = 1; + break; + + case 3: + envIdx = 2; + break; + + case 4: + envIdx = 3; + break; + + default: + /* unsupported number of envelopes */ + envIdx = 0; + } + + return envIdx; +} + +static INT encodePSExtension(const HANDLE_PS_OUT psOut, + HANDLE_FDK_BITSTREAM hBitBuf) { + INT bitCnt = 0; + + if (psOut->enableIpdOpd == 1) { + INT ipdOpdBits = 0; + INT extSize = (2 + encodeIpdOpd(psOut, NULL) + 7) >> 3; + + if (extSize < 15) { + bitCnt += FDKsbrEnc_WriteBits_ps(hBitBuf, extSize, 4); + } else { + bitCnt += FDKsbrEnc_WriteBits_ps(hBitBuf, 15, 4); + bitCnt += FDKsbrEnc_WriteBits_ps(hBitBuf, (extSize - 15), 8); + } + + /* write ipd opd data */ + ipdOpdBits += FDKsbrEnc_WriteBits_ps(hBitBuf, PS_EXT_ID_V0, 2); + ipdOpdBits += encodeIpdOpd(psOut, hBitBuf); + + /* byte align the ipd opd data */ + if (ipdOpdBits % 8) + ipdOpdBits += FDKsbrEnc_WriteBits_ps(hBitBuf, 0, (8 - (ipdOpdBits % 8))); + + bitCnt += ipdOpdBits; + } + + return (bitCnt); +} + +INT FDKsbrEnc_WritePSBitstream(const HANDLE_PS_OUT psOut, + HANDLE_FDK_BITSTREAM hBitBuf) { + INT psExtEnable = 0; + INT bitCnt = 0; + INT error = 0; + INT env; + + if (psOut != NULL) { + /* PS HEADER */ + bitCnt += FDKsbrEnc_WriteBits_ps(hBitBuf, psOut->enablePSHeader, 1); + + if (psOut->enablePSHeader) { + bitCnt += FDKsbrEnc_WriteBits_ps(hBitBuf, psOut->enableIID, 1); + if (psOut->enableIID) { + bitCnt += FDKsbrEnc_WriteBits_ps(hBitBuf, psOut->iidMode, 3); + } + bitCnt += FDKsbrEnc_WriteBits_ps(hBitBuf, psOut->enableICC, 1); + if (psOut->enableICC) { + bitCnt += FDKsbrEnc_WriteBits_ps(hBitBuf, psOut->iccMode, 3); + } + if (psOut->enableIpdOpd) { + psExtEnable = 1; + } + bitCnt += FDKsbrEnc_WriteBits_ps(hBitBuf, psExtEnable, 1); + } + + /* Frame class, number of envelopes */ + bitCnt += FDKsbrEnc_WriteBits_ps(hBitBuf, psOut->frameClass, 1); + bitCnt += FDKsbrEnc_WriteBits_ps( + hBitBuf, getEnvIdx(psOut->nEnvelopes, psOut->frameClass), 2); + + if (psOut->frameClass == 1) { + for (env = 0; env < psOut->nEnvelopes; env++) { + bitCnt += FDKsbrEnc_WriteBits_ps(hBitBuf, psOut->frameBorder[env], 5); + } + } + + if (psOut->enableIID == 1) { + INT *iidLast = psOut->iidLast; + for (env = 0; env < psOut->nEnvelopes; env++) { + bitCnt += FDKsbrEnc_WriteBits_ps(hBitBuf, psOut->deltaIID[env], 1); + bitCnt += FDKsbrEnc_EncodeIid( + hBitBuf, psOut->iid[env], iidLast, getNoBands(psOut->iidMode), + (PS_IID_RESOLUTION)getIIDRes(psOut->iidMode), psOut->deltaIID[env], + &error); + + iidLast = psOut->iid[env]; + } + } + + if (psOut->enableICC == 1) { + INT *iccLast = psOut->iccLast; + for (env = 0; env < psOut->nEnvelopes; env++) { + bitCnt += FDKsbrEnc_WriteBits_ps(hBitBuf, psOut->deltaICC[env], 1); + bitCnt += FDKsbrEnc_EncodeIcc(hBitBuf, psOut->icc[env], iccLast, + getNoBands(psOut->iccMode), + psOut->deltaICC[env], &error); + + iccLast = psOut->icc[env]; + } + } + + if (psExtEnable != 0) { + bitCnt += encodePSExtension(psOut, hBitBuf); + } + + } /* if(psOut != NULL) */ + + return bitCnt; +} |