diff options
author | Matthias P. Braendli <matthias.braendli@mpb.li> | 2013-12-14 17:32:17 +0100 |
---|---|---|
committer | Matthias P. Braendli <matthias.braendli@mpb.li> | 2018-09-12 14:20:53 +0200 |
commit | bdfafd471e3c7c240b5c78e8d1233ce61f17c296 (patch) | |
tree | 4cff9d116268d3941bd328e606c15f0ee8d3a6df | |
parent | 651ff34d8d35fb6a3b75471d54b271852f5924cc (diff) | |
download | fdk-aac-bdfafd471e3c7c240b5c78e8d1233ce61f17c296.tar.gz fdk-aac-bdfafd471e3c7c240b5c78e8d1233ce61f17c296.tar.bz2 fdk-aac-bdfafd471e3c7c240b5c78e8d1233ce61f17c296.zip |
Add DAB+ support
-rw-r--r-- | Makefile.am | 3 | ||||
-rw-r--r-- | README.md | 9 | ||||
-rwxr-xr-x | bootstrap | 4 | ||||
-rw-r--r-- | libAACenc/include/aacenc_lib.h | 2 | ||||
-rw-r--r-- | libAACenc/src/aacenc.cpp | 32 | ||||
-rw-r--r-- | libAACenc/src/aacenc_lib.cpp | 106 | ||||
-rw-r--r-- | libAACenc/src/aacenc_tns.cpp | 19 | ||||
-rw-r--r-- | libAACenc/src/bitenc.cpp | 56 | ||||
-rw-r--r-- | libAACenc/src/dyn_bits.cpp | 2 | ||||
-rw-r--r-- | libAACenc/src/psy_configuration.cpp | 180 | ||||
-rw-r--r-- | libAACenc/src/psy_const.h | 1 | ||||
-rw-r--r-- | libAACenc/src/qc_main.cpp | 3 | ||||
-rw-r--r-- | libFDK/src/FDK_crc.cpp | 49 | ||||
-rw-r--r-- | libFDK/src/FDK_tools_rom.cpp | 3 | ||||
-rw-r--r-- | libFDK/src/mdct.cpp | 3 | ||||
-rw-r--r-- | libMpegTPEnc/src/tpenc_dab.cpp | 467 | ||||
-rw-r--r-- | libMpegTPEnc/src/tpenc_dab.h | 217 | ||||
-rw-r--r-- | libMpegTPEnc/src/tpenc_lib.cpp | 51 | ||||
-rw-r--r-- | libSBRenc/src/env_est.cpp | 1 | ||||
-rw-r--r-- | libSBRenc/src/sbr_encoder.cpp | 2 | ||||
-rw-r--r-- | libSYS/include/FDK_audio.h | 16 |
21 files changed, 1191 insertions, 35 deletions
diff --git a/Makefile.am b/Makefile.am index fe6b867..2e78a3f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -161,7 +161,8 @@ MPEGTPENC_SRC = \ libMpegTPEnc/src/tpenc_adts.cpp \ libMpegTPEnc/src/tpenc_asc.cpp \ libMpegTPEnc/src/tpenc_latm.cpp \ - libMpegTPEnc/src/tpenc_lib.cpp + libMpegTPEnc/src/tpenc_lib.cpp \ + libMpegTPEnc/src/tpenc_dab.cpp PCMUTILS_SRC = \ libPCMutils/src/limiter.cpp \ diff --git a/README.md b/README.md new file mode 100644 index 0000000..308f292 --- /dev/null +++ b/README.md @@ -0,0 +1,9 @@ +A patched version of fdk-aac with DAB+ support +============================================== + +This is a modified version of fdk-aac that supports the AOTs +required for DAB+ encoding. + +This library is a dependency for ODR-AudioEnc. + +See www.opendigitalradio.org for more diff --git a/bootstrap b/bootstrap new file mode 100755 index 0000000..a3394ab --- /dev/null +++ b/bootstrap @@ -0,0 +1,4 @@ +#! /bin/sh + +autoreconf --install && \ + echo "You can call ./configure now" diff --git a/libAACenc/include/aacenc_lib.h b/libAACenc/include/aacenc_lib.h index fa41ee6..231bbb4 100644 --- a/libAACenc/include/aacenc_lib.h +++ b/libAACenc/include/aacenc_lib.h @@ -1340,6 +1340,7 @@ typedef enum { AACENC_GRANULE_LENGTH = 0x0105, /*!< Core encoder (AAC) audio frame length in samples: - 1024: Default configuration. + - 960: DRM/DAB+. - 512: Default length in LD/ELD configuration. - 480: Length in LD/ELD configuration. - 256: Length for ELD reduced delay mode (x2). @@ -1503,6 +1504,7 @@ typedef enum { 0x0303, /*!< Number of sub frames in a transport frame for LOAS/LATM or ADTS (default 1). - ADTS: Maximum number of sub frames restricted to 4. + - DAB+: Maximum number of sub frames restricted to 6. - LOAS/LATM: Maximum number of sub frames restricted to 2.*/ AACENC_AUDIOMUXVER = diff --git a/libAACenc/src/aacenc.cpp b/libAACenc/src/aacenc.cpp index 8b8a1ad..372df31 100644 --- a/libAACenc/src/aacenc.cpp +++ b/libAACenc/src/aacenc.cpp @@ -186,6 +186,7 @@ INT FDKaacEnc_LimitBitrate(HANDLE_TRANSPORTENC hTpEnc, AUDIO_OBJECT_TYPE aot, } while (prevBitRate != bitRate && iter++ < 3); + //fprintf(stderr, "FDKaacEnc_LimitBitrate(): bitRate=%d\n", bitRate); return bitRate; } @@ -431,6 +432,36 @@ AAC_ENCODER_ERROR FDKaacEnc_Initialize( return AAC_ENC_UNSUPPORTED_BITRATE; } + INT superframe_size = 110*8*(config->bitRate/8000); + INT frames_per_superframe = 6; + INT staticBits = 0; + if((config->syntaxFlags & AC_DAB) && hTpEnc) { + staticBits = transportEnc_GetStaticBits(hTpEnc, 0); + switch(config->sampleRate) { + case 48000: + frames_per_superframe=6; + break; + case 32000: + frames_per_superframe=4; + break; + case 24000: + frames_per_superframe=3; + break; + case 16000: + frames_per_superframe=2; + break; + } + + //config->nSubFrames = frames_per_superframe; + //fprintf(stderr, "DAB+ superframe size=%d\n", superframe_size); + config->bitRate = (superframe_size - 16*(frames_per_superframe-1) - staticBits) * 1000/120; + //fprintf(stderr, "DAB+ tuned bitrate=%d\n", config->bitRate); + config->maxBitsPerFrame = (superframe_size - 16*(frames_per_superframe-1) - staticBits) / frames_per_superframe; + config->maxBitsPerFrame += 7; /*padding*/ + //config->bitreservoir=(superframe_size - 16*(frames_per_superframe-1) - staticBits - 2*8)/frames_per_superframe; + //fprintf(stderr, "DAB+ tuned maxBitsPerFrame=%d\n", (superframe_size - 16*(frames_per_superframe-1) - staticBits)/frames_per_superframe); + } + /* check bit rate */ if (FDKaacEnc_LimitBitrate( @@ -454,6 +485,7 @@ AAC_ENCODER_ERROR FDKaacEnc_Initialize( /* check frame length */ switch (config->framelength) { case 1024: + case 960: if (isLowDelay(config->audioObjectType)) { return AAC_ENC_INVALID_FRAME_LENGTH; } diff --git a/libAACenc/src/aacenc_lib.cpp b/libAACenc/src/aacenc_lib.cpp index 2f34d4d..220830a 100644 --- a/libAACenc/src/aacenc_lib.cpp +++ b/libAACenc/src/aacenc_lib.cpp @@ -99,7 +99,7 @@ amm-info@iis.fraunhofer.de Description: FDK HE-AAC Encoder interface library functions *******************************************************************************/ - +#include <stdio.h> #include "aacenc_lib.h" #include "FDK_audio.h" #include "aacenc.h" @@ -368,7 +368,9 @@ static inline INT isSbrActive(const HANDLE_AACENC_CONFIG hAacConfig) { * AOT_AAC_LC */ if ((hAacConfig->audioObjectType == AOT_SBR) || (hAacConfig->audioObjectType == AOT_PS) || - (hAacConfig->audioObjectType == AOT_MP2_SBR)) { + (hAacConfig->audioObjectType == AOT_MP2_SBR) || + (hAacConfig->audioObjectType == AOT_DABPLUS_SBR) || + (hAacConfig->audioObjectType == AOT_DABPLUS_PS)) { sbrUsed = 1; } if (hAacConfig->audioObjectType == AOT_ER_AAC_ELD && @@ -382,9 +384,10 @@ static inline INT isSbrActive(const HANDLE_AACENC_CONFIG hAacConfig) { static inline INT isPsActive(const AUDIO_OBJECT_TYPE audioObjectType) { INT psUsed = 0; - if (audioObjectType == AOT_PS) { - psUsed = 1; - } + if ((audioObjectType == AOT_PS) || + (audioObjectType == AOT_DABPLUS_PS)) { + psUsed = 1; + } return (psUsed); } @@ -417,7 +420,9 @@ static SBR_PS_SIGNALING getSbrSignalingMode( if ((audioObjectType == AOT_AAC_LC) || (audioObjectType == AOT_SBR) || (audioObjectType == AOT_PS) || (audioObjectType == AOT_MP2_AAC_LC) || - (audioObjectType == AOT_MP2_SBR)) { + (audioObjectType == AOT_MP2_SBR) || + (audioObjectType == AOT_DABPLUS_SBR) || + (audioObjectType == AOT_DABPLUS_PS)) { switch (transportType) { case TT_MP4_ADIF: case TT_MP4_ADTS: @@ -472,11 +477,17 @@ static void FDKaacEnc_MapConfig(CODER_CONFIG *const cc, /* Map virtual aot to transport aot. */ switch (hAacConfig->audioObjectType) { case AOT_MP2_AAC_LC: + case AOT_DABPLUS_AAC_LC: transport_AOT = AOT_AAC_LC; break; case AOT_MP2_SBR: + case AOT_DABPLUS_SBR: transport_AOT = AOT_SBR; cc->flags |= CC_SBR; + break; + case AOT_DABPLUS_PS: + transport_AOT = AOT_PS; + cc->flags |= CC_SBR; break; default: transport_AOT = hAacConfig->audioObjectType; @@ -525,9 +536,27 @@ static void FDKaacEnc_MapConfig(CODER_CONFIG *const cc, cc->flags |= CC_IS_BASELAYER; cc->channelMode = hAacConfig->channelMode; - cc->nSubFrames = (hAacConfig->nSubFrames > 1 && extCfg->userTpNsubFrames == 1) +if (extCfg->userTpType == TT_DABPLUS && hAacConfig->nSubFrames==1) { + switch(hAacConfig->sampleRate) { + case 48000: + cc->nSubFrames=6; + break; + case 32000: + cc->nSubFrames=4; + break; + case 24000: + cc->nSubFrames=3; + break; + case 16000: + cc->nSubFrames=2; + break; + } + //fprintf(stderr, "hAacConfig->nSubFrames=%d hAacConfig->sampleRate=%d\n", hAacConfig->nSubFrames, hAacConfig->sampleRate); + } else { + cc->nSubFrames = (hAacConfig->nSubFrames > 1 && extCfg->userTpNsubFrames == 1) ? hAacConfig->nSubFrames : extCfg->userTpNsubFrames; + } cc->flags |= (extCfg->userTpProtection) ? CC_PROTECTION : 0; @@ -805,6 +834,7 @@ static INT aacEncoder_LimitBitrate(const HANDLE_TRANSPORTENC hTpEnc, bitRate); } + //fprintf(stderr, "aacEncoder_LimitBitrate(): bitRate=%d\n", bitRate); return bitRate; } @@ -919,6 +949,21 @@ static AACENC_ERROR FDKaacEnc_AdjustEncSettings(HANDLE_AACENCODER hAacEncoder, return AACENC_INVALID_CONFIG; } break; + + case AOT_DABPLUS_SBR: + case AOT_DABPLUS_PS: + hAacConfig->syntaxFlags |= ((config->userSbrEnabled) ? AC_SBR_PRESENT : 0); + case AOT_DABPLUS_AAC_LC: + config->userTpType = (config->userTpType!=TT_UNKNOWN) ? config->userTpType : TT_DABPLUS; + hAacConfig->framelength = (config->userFramelength!=(UINT)-1) ? config->userFramelength : 960; + if (hAacConfig->framelength != 960) { + return AACENC_INVALID_CONFIG; + } + config->userTpSignaling=2; + if(config->userTpType == TT_DABPLUS) + hAacConfig->syntaxFlags |= AC_DAB; + break; + case AOT_ER_AAC_LD: hAacConfig->epConfig = 0; hAacConfig->syntaxFlags |= AC_ER | AC_LD; @@ -1143,7 +1188,23 @@ static AACENC_ERROR FDKaacEnc_AdjustEncSettings(HANDLE_AACENCODER hAacEncoder, break; } - /* Configure PNS */ +#if 0 // TODO Is this still needed? + /* We need the frame length to call aacEncoder_LimitBitrate() */ + hAacConfig->bitRate = aacEncoder_LimitBitrate( + NULL, + hAacConfig->sampleRate, + hAacConfig->framelength, + hAacConfig->nChannels, + hAacConfig->channelMode, + hAacConfig->bitRate, + hAacConfig->nSubFrames, + isSbrActive(hAacConfig), + hAacConfig->sbrRatio, + hAacConfig->audioObjectType + ); +#endif + +/* Configure PNS */ if (AACENC_BR_MODE_IS_VBR(hAacConfig->bitrateMode) /* VBR without PNS. */ || (hAacConfig->useTns == 0)) /* TNS required. */ { @@ -2061,7 +2122,7 @@ AACENC_ERROR aacEncGetLibInfo(LIB_INFO *info) { LIB_VERSION_STRING(&info[i]); /* Capability flags */ - info[i].flags = 0 | CAPF_AAC_1024 | CAPF_AAC_LC | CAPF_AAC_512 | + info[i].flags = 0 | CAPF_AAC_1024 | CAPF_AAC_LC | CAPF_AAC_960| CAPF_AAC_512 | CAPF_AAC_480 | CAPF_AAC_DRC | CAPF_AAC_ELD_DOWNSCALE; /* End of flags */ @@ -2086,18 +2147,21 @@ AACENC_ERROR aacEncoder_SetParam(const HANDLE_AACENCODER hAacEncoder, /* check if AOT matches the allocated modules */ switch (value) { case AOT_PS: + case AOT_DABPLUS_PS: if (!(hAacEncoder->encoder_modis & (ENC_MODE_FLAG_PS))) { err = AACENC_INVALID_CONFIG; goto bail; } case AOT_SBR: case AOT_MP2_SBR: + case AOT_DABPLUS_SBR: if (!(hAacEncoder->encoder_modis & (ENC_MODE_FLAG_SBR))) { err = AACENC_INVALID_CONFIG; goto bail; } case AOT_AAC_LC: case AOT_MP2_AAC_LC: + case AOT_DABPLUS_AAC_LC: case AOT_ER_AAC_LD: case AOT_ER_AAC_ELD: if (!(hAacEncoder->encoder_modis & (ENC_MODE_FLAG_AAC))) { @@ -2129,6 +2193,8 @@ AACENC_ERROR aacEncoder_SetParam(const HANDLE_AACENCODER hAacEncoder, case 3: case 4: case 5: + case 7: + case 8: settings->userBitrateMode = value; hAacEncoder->InitFlags |= AACENC_INIT_CONFIG | AACENC_INIT_TRANSPORT; @@ -2215,6 +2281,7 @@ AACENC_ERROR aacEncoder_SetParam(const HANDLE_AACENCODER hAacEncoder, if (settings->userFramelength != value) { switch (value) { case 1024: + case 960: case 512: case 480: case 256: @@ -2257,17 +2324,18 @@ AACENC_ERROR aacEncoder_SetParam(const HANDLE_AACENCODER hAacEncoder, break; case AACENC_TRANSMUX: if (settings->userTpType != (TRANSPORT_TYPE)value) { - TRANSPORT_TYPE type = (TRANSPORT_TYPE)value; - UINT flags = hAacEncoder->CAPF_tpEnc; + TRANSPORT_TYPE type = (TRANSPORT_TYPE)value; + UINT flags = hAacEncoder->CAPF_tpEnc; if (!(((type == TT_MP4_ADIF) && (flags & CAPF_ADIF)) || - ((type == TT_MP4_ADTS) && (flags & CAPF_ADTS)) || - ((type == TT_MP4_LATM_MCP0) && - ((flags & CAPF_LATM) && (flags & CAPF_RAWPACKETS))) || - ((type == TT_MP4_LATM_MCP1) && - ((flags & CAPF_LATM) && (flags & CAPF_RAWPACKETS))) || - ((type == TT_MP4_LOAS) && (flags & CAPF_LOAS)) || - ((type == TT_MP4_RAW) && (flags & CAPF_RAWPACKETS)))) { + ((type == TT_MP4_ADTS) && (flags & CAPF_ADTS)) || + ((type == TT_MP4_LATM_MCP0) && + ((flags & CAPF_LATM) && (flags & CAPF_RAWPACKETS))) || + ((type == TT_MP4_LATM_MCP1) && + ((flags & CAPF_LATM) && (flags & CAPF_RAWPACKETS))) || + ((type == TT_MP4_LOAS) && (flags & CAPF_LOAS)) || + ((type == TT_MP4_RAW) && (flags & CAPF_RAWPACKETS)) || + ((type == TT_DABPLUS) && ((flags & CAPF_DAB_AAC) && (flags & CAPF_RAWPACKETS))) )) { err = AACENC_INVALID_CONFIG; break; } @@ -2317,7 +2385,7 @@ AACENC_ERROR aacEncoder_SetParam(const HANDLE_AACENCODER hAacEncoder, break; case AACENC_TPSUBFRAMES: if (settings->userTpNsubFrames != value) { - if (!((value >= 1) && (value <= 4))) { + if (!((value >= 1) && (value <= 6))) { err = AACENC_INVALID_CONFIG; break; } diff --git a/libAACenc/src/aacenc_tns.cpp b/libAACenc/src/aacenc_tns.cpp index 4462600..3436150 100644 --- a/libAACenc/src/aacenc_tns.cpp +++ b/libAACenc/src/aacenc_tns.cpp @@ -196,6 +196,22 @@ static const TNS_MAX_TAB_ENTRY tnsMaxBandsTab1024[] = { {44100, {42, 14}}, {32000, {51, 14}}, {24000, {46, 14}}, {22050, {46, 14}}, {16000, {42, 14}}, {12000, {42, 14}}, {11025, {42, 14}}, {8000, {39, 14}}}; +static const TNS_MAX_TAB_ENTRY tnsMaxBandsTab960[] = +{ + { 96000, { 31, 9}}, + { 88200, { 31, 9}}, + { 64000, { 34, 10}}, + { 48000, { 49, 14}}, + { 44100, { 49, 14}}, + { 32000, { 49, 14}}, + { 24000, { 46, 15}}, + { 22050, { 46, 14}}, + { 16000, { 46, 15}}, + { 12000, { 42, 15}}, + { 11025, { 42, 15}}, + { 8000, { 40, 15}} +}; + static const TNS_MAX_TAB_ENTRY tnsMaxBandsTab120[] = { {48000, {12, -1}}, /* 48000 */ {44100, {12, -1}}, /* 44100 */ @@ -278,6 +294,9 @@ static INT getTnsMaxBands(const INT sampleRate, const INT granuleLength, switch (granuleLength) { case 960: + pMaxBandsTab = tnsMaxBandsTab960; + maxBandsTabSize = sizeof(tnsMaxBandsTab960) / sizeof(TNS_MAX_TAB_ENTRY); + break; case 1024: pMaxBandsTab = tnsMaxBandsTab1024; maxBandsTabSize = sizeof(tnsMaxBandsTab1024) / sizeof(TNS_MAX_TAB_ENTRY); diff --git a/libAACenc/src/bitenc.cpp b/libAACenc/src/bitenc.cpp index 652d1fd..18dfe95 100644 --- a/libAACenc/src/bitenc.cpp +++ b/libAACenc/src/bitenc.cpp @@ -100,6 +100,7 @@ amm-info@iis.fraunhofer.de *******************************************************************************/ +#include <stdio.h> #include "bitenc.h" #include "bit_cnt.h" #include "dyn_bits.h" @@ -1195,6 +1196,23 @@ AAC_ENCODER_ERROR FDKaacEnc_WriteBitstream(HANDLE_TRANSPORTENC hTpEnc, frameBits = bitMarkUp = alignAnchor; + + /* Write DSEs first in case of DAB */ + for (n = 0; (n < qcOut->nExtensions) && (n < (2+2)); n++) { + if ( (syntaxFlags & AC_DAB) && + (qcOut->extension[n].type == EXT_DATA_ELEMENT) ) { + FDKaacEnc_writeExtensionData( hTpEnc, + &qcOut->extension[n], + 0, + alignAnchor, + syntaxFlags, + aot, + epConfig ); + } + + /* For EXT_FIL or EXT_FILL_DATA we could do an additional sanity check here */ + } + /* Channel element loop */ for (i = 0; i < channelMapping->nElements; i++) { ELEMENT_INFO elInfo = channelMapping->elInfo[i]; @@ -1281,20 +1299,40 @@ AAC_ENCODER_ERROR FDKaacEnc_WriteBitstream(HANDLE_TRANSPORTENC hTpEnc, n = qcOut->nExtensions; /* Add fill data / stuffing bits */ - qcOut->extension[n].type = EXT_FILL_DATA; - qcOut->extension[n].nPayloadBits = qcOut->totFillBits; - qcOut->nExtensions++; + n = qcOut->nExtensions; + +// if (!(syntaxFlags & AC_DAB)) { + qcOut->extension[n].type = EXT_FILL_DATA; + qcOut->extension[n].nPayloadBits = qcOut->totFillBits; + qcOut->nExtensions++; +// } else { +// doByteAlign = 0; +// } + if (syntaxFlags & AC_DAB) + doByteAlign = 0; /* Write global extension payload and fill data */ - for (n = 0; (n < qcOut->nExtensions) && (n < (2 + 2)); n++) { - FDKaacEnc_writeExtensionData(hTpEnc, &qcOut->extension[n], 0, alignAnchor, - syntaxFlags, aot, epConfig); + for (n = 0; (n < qcOut->nExtensions) && (n < (2+2)); n++) + { + if ( !(syntaxFlags & AC_DAB) || + ( (syntaxFlags & AC_DAB) && + (qcOut->extension[n].type != EXT_DATA_ELEMENT) + ) + ) { + FDKaacEnc_writeExtensionData( hTpEnc, + &qcOut->extension[n], + 0, + alignAnchor, + syntaxFlags, + aot, + epConfig ); + } /* For EXT_FIL or EXT_FILL_DATA we could do an additional sanity check here */ } - if (!(syntaxFlags & (AC_SCALABLE | AC_ER))) { + if (!(syntaxFlags & (AC_SCALABLE | AC_ER | AC_DAB))) { FDKwriteBits(hBs, ID_END, EL_ID_BITS); } @@ -1312,9 +1350,11 @@ AAC_ENCODER_ERROR FDKaacEnc_WriteBitstream(HANDLE_TRANSPORTENC hTpEnc, transportEnc_EndAccessUnit(hTpEnc, &frameBits); - if (frameBits != qcOut->totalBits + qcKernel->globHdrBits) { + if (frameBits != qcOut->totalBits + qcKernel->globHdrBits){ + fprintf(stderr, "frameBits != qcOut->totalBits + qcKernel->globHdrBits: %d != %d + %d", frameBits, qcOut->totalBits, qcKernel->globHdrBits); return AAC_ENC_WRITTEN_BITS_ERROR; } + //fprintf(stderr, "ErrorStatus=%d", ErrorStatus); return ErrorStatus; } diff --git a/libAACenc/src/dyn_bits.cpp b/libAACenc/src/dyn_bits.cpp index 74baeb8..b52dc2e 100644 --- a/libAACenc/src/dyn_bits.cpp +++ b/libAACenc/src/dyn_bits.cpp @@ -363,6 +363,8 @@ static void FDKaacEnc_noiselessCounter( break; } + FDK_ASSERT(sideInfoTab != NULL); + sectionData->noOfSections = 0; sectionData->huffmanBits = 0; sectionData->sideInfoBits = 0; diff --git a/libAACenc/src/psy_configuration.cpp b/libAACenc/src/psy_configuration.cpp index eef90bc..b444b58 100644 --- a/libAACenc/src/psy_configuration.cpp +++ b/libAACenc/src/psy_configuration.cpp @@ -130,6 +130,161 @@ static const SFB_INFO_TAB sfbInfoTab[] = { }; + + +const SFB_PARAM_LONG p_FDKaacEnc_8000_long_960 = { + 40, + { 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 16, + 16, 16, 16, 16, 16, 16, 20, 20, 20, 20, 24, 24, 24, 28, + 28, 32, 36, 36, 40, 44, 48, 52, 56, 60, 64, 16 } +}; +const SFB_PARAM_SHORT p_FDKaacEnc_8000_short_120 = { + 15, + { 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 12, 16, 20, 12 } +}; + +const SFB_PARAM_LONG p_FDKaacEnc_11025_long_960 = { + 42, + { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 16, 16, 16, 16, 20, 20, 20, 24, + 24, 28, 28, 32, 36, 40, 40, 44, 48, 52, 56, 60, 64, 64 } +}; +const SFB_PARAM_SHORT p_FDKaacEnc_11025_short_120 = { + 15, + { 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 12, 12, 16, 20, 12 } +}; + +const SFB_PARAM_LONG p_FDKaacEnc_12000_long_960 = { + 42, + { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 16, 16, 16, 16, 20, 20, 20, 24, + 24, 28, 28, 32, 36, 40, 40, 44, 48, 52, 56, 60, 64, 64 } +}; +const SFB_PARAM_SHORT p_FDKaacEnc_12000_short_120 = { + 15, + { 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 12, 12, 16, 20, 12 } +}; + +const SFB_PARAM_LONG p_FDKaacEnc_16000_long_960 = { + 42, + { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 16, 16, 16, 16, 20, 20, 20, 24, + 24, 28, 28, 32, 36, 40, 40, 44, 48, 52, 56, 60, 64, 64 } +}; +const SFB_PARAM_SHORT p_FDKaacEnc_16000_short_120 = { + 15, + { 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 12, 12, 16, 20, 12 } +}; + +const SFB_PARAM_LONG p_FDKaacEnc_22050_long_960 = { + 46, + { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 12, 12, 12, 12, 16, 16, 16, + 20, 20, 24, 24, 28, 28, 32, 36, 36, 40, 44, 48, 52, 52, + 64, 64, 64, 64 } +}; +const SFB_PARAM_SHORT p_FDKaacEnc_22050_short_120 = { + 15, + { 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 12, 12, 16, 16, 12 } +}; + +const SFB_PARAM_LONG p_FDKaacEnc_24000_long_960 = { + 46, + { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 12, 12, 12, 12, 16, 16, 16, + 20, 20, 24, 24, 28, 28, 32, 36, 36, 40, 44, 48, 52, 52, + 64, 64, 64, 64 } +}; +const SFB_PARAM_SHORT p_FDKaacEnc_24000_short_120 = { + 15, + { 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 12, 12, 16, 16, 12 } +}; + +const SFB_PARAM_LONG p_FDKaacEnc_32000_long_960 = { + 49, + { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, 12, 12, 12, + 12, 16, 16, 20, 20, 24, 24, 28, 28, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32 } +}; + +const SFB_PARAM_SHORT p_FDKaacEnc_32000_short_120 = { + 14, + { 4, 4, 4, 4, 4, 8, 8, 8, 12, 12, 12, 16, 16, 8 } +}; + +const SFB_PARAM_LONG p_FDKaacEnc_44100_long_960 = { + 49, + { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, + 8, 8, 8, 12, 12, 12, 12, 16, 16, 20, 20, 24, 24, 28, + 28, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32 } +}; + +const SFB_PARAM_SHORT p_FDKaacEnc_44100_short_120 = { + 14, + { 4, 4, 4, 4, 4, 8, 8, 8, 12, 12, 12, 16, 16, 8 } +}; + +const SFB_PARAM_LONG p_FDKaacEnc_48000_long_960 = { + 49, + { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, + 8, 8, 8, 12, 12, 12, 12, 16, 16, 20, 20, 24, 24, 28, + 28, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32 } +}; +const SFB_PARAM_SHORT p_FDKaacEnc_48000_short_120 = { + 14, + { 4, 4, 4, 4, 4, 8, 8, 8, 12, 12, 12, 16, 16, 8 } +}; + +const SFB_PARAM_LONG p_FDKaacEnc_64000_long_960 = { + 46, + { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 12, 12, + 12, 16, 16, 16, 20, 24, 24, 28, 36, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 16 } +}; +const SFB_PARAM_SHORT p_FDKaacEnc_64000_short_120 = { + 12, + { 4, 4, 4, 4, 4, 4, 8, 8, 8, 16, 28, 28 } +}; + +const SFB_PARAM_LONG p_FDKaacEnc_88200_long_960 = { + 40, + { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 12, + 12, 12, 12, 12, 16, 16, 24, 28, 36, 44, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64 } +}; +const SFB_PARAM_SHORT p_FDKaacEnc_88200_short_120 = { + 12, + { 4, 4, 4, 4, 4, 4, 8, 8, 8, 16, 28, 28 } +}; + +const SFB_PARAM_LONG p_FDKaacEnc_96000_long_960 = { + 40, + { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 12, + 12, 12, 12, 12, 16, 16, 24, 28, 36, 44, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64 } +}; +const SFB_PARAM_SHORT p_FDKaacEnc_96000_short_120 = { + 12, + { 4, 4, 4, 4, 4, 4, 8, 8, 8, 16, 28, 28 } +}; + + +static const SFB_INFO_TAB sfbInfoTab960[] = { + { 8000, &p_FDKaacEnc_8000_long_960, &p_FDKaacEnc_8000_short_120}, + {11025, &p_FDKaacEnc_11025_long_960, &p_FDKaacEnc_11025_short_120}, + {12000, &p_FDKaacEnc_12000_long_960, &p_FDKaacEnc_12000_short_120}, + {16000, &p_FDKaacEnc_16000_long_960, &p_FDKaacEnc_16000_short_120}, + {22050, &p_FDKaacEnc_22050_long_960, &p_FDKaacEnc_22050_short_120}, + {24000, &p_FDKaacEnc_24000_long_960, &p_FDKaacEnc_24000_short_120}, + {32000, &p_FDKaacEnc_32000_long_960, &p_FDKaacEnc_32000_short_120}, + {44100, &p_FDKaacEnc_44100_long_960, &p_FDKaacEnc_44100_short_120}, + {48000, &p_FDKaacEnc_48000_long_960, &p_FDKaacEnc_48000_short_120}, + {64000, &p_FDKaacEnc_64000_long_960, &p_FDKaacEnc_64000_short_120}, + {88200, &p_FDKaacEnc_88200_long_960, &p_FDKaacEnc_88200_short_120}, + {96000, &p_FDKaacEnc_96000_long_960, &p_FDKaacEnc_96000_short_120}, +}; + + /* 22050 and 24000 Hz */ static const SFB_PARAM_LONG p_22050_long_512 = { 31, {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 12, 12, @@ -204,10 +359,13 @@ AAC_ENCODER_ERROR FDKaacEnc_initSfbTable(const LONG sampleRate, */ switch (granuleLength) { case 1024: - case 960: sfbInfo = sfbInfoTab; size = (INT)(sizeof(sfbInfoTab) / sizeof(SFB_INFO_TAB)); break; + case 960: + sfbInfo = sfbInfoTab960; + size = (INT)(sizeof(sfbInfoTab960)/sizeof(SFB_INFO_TAB)); + break; case 512: sfbInfo = sfbInfoTabLD512; size = sizeof(sfbInfoTabLD512); @@ -287,23 +445,31 @@ static FIXP_DBL FDKaacEnc_BarcLineValue(INT noOfLines, INT fftLine, center_freq = fftLine * samplingFreq; /* q11 or q8 */ + switch (noOfLines) { case 1024: center_freq = center_freq << 2; /* q13 */ break; + case 960: + center_freq = fMult(center_freq, INV480) << 3; + break; case 128: center_freq = center_freq << 5; /* q13 */ break; + case 120: + center_freq = fMult(center_freq, INV480) << 6; + break; case 512: - center_freq = (fftLine * samplingFreq) << 3; // q13 + center_freq = (fftLine * samplingFreq) << 3; // q13 break; case 480: - center_freq = fMult(center_freq, INV480) << 4; // q13 + center_freq = fMult(center_freq, INV480) << 4; // q13 break; default: center_freq = (FIXP_DBL)0; } + x1 = fMult(center_freq, FOURBY3EM4); /* q13 * q43 - (DFRACT_BITS-1) = q25 */ x2 = fMult(center_freq, PZZZ76) << 2; /* q13 * q41 - (DFRACT_BITS-1) + 2 = q25 */ @@ -468,6 +634,14 @@ static void FDKaacEnc_initMinSnr(const LONG bitrate, const LONG samplerate, qperwin = qperwin - 9; pePerWindow = fMult(pePerWindow, FL2FXCONST_DBL(480.f / 512.f)); break; + case 960: + pePerWindow = fMult(pePerWindow, FL2FXCONST_DBL(960.f/1024.f)); + qperwin = qperwin - 10; + break; + case 120: + pePerWindow = fMult(pePerWindow, FL2FXCONST_DBL(120.f/128.f)); + qperwin = qperwin - 7; + break; } /* for short blocks it is assumed that more bits are available */ diff --git a/libAACenc/src/psy_const.h b/libAACenc/src/psy_const.h index c2d5304..c3f3f64 100644 --- a/libAACenc/src/psy_const.h +++ b/libAACenc/src/psy_const.h @@ -108,6 +108,7 @@ amm-info@iis.fraunhofer.de #define TRANS_FAC 8 /* encoder short long ratio */ +#define FRAME_LEN_LONG_960 (960) #define FRAME_MAXLEN_SHORT ((1024) / TRANS_FAC) #define FRAME_LEN_SHORT_128 ((1024) / TRANS_FAC) #define FRAME_LEN_SHORT_120 (FRAME_LEN_LONG_960 / TRANS_FAC) diff --git a/libAACenc/src/qc_main.cpp b/libAACenc/src/qc_main.cpp index ba3bc7e..0bf234c 100644 --- a/libAACenc/src/qc_main.cpp +++ b/libAACenc/src/qc_main.cpp @@ -484,6 +484,7 @@ AAC_ENCODER_ERROR FDKaacEnc_AdjustBitrate( { INT paddingOn; INT frameLen; + //fprintf(stderr, "hQC->padding.paddingRest=%d bytes! (before)\n", hQC->padding.paddingRest); /* Do we need an extra padding byte? */ paddingOn = FDKaacEnc_framePadding(bitRate, sampleRate, granuleLength, @@ -1373,6 +1374,8 @@ AAC_ENCODER_ERROR FDKaacEnc_FinalizeBitConsumption( qcOut->totFillBits = FDKaacEnc_writeExtensionData(NULL, &fillExtPayload, 0, 0, syntaxFlags, aot, epConfig); + //fprintf(stderr, "FinalizeBitConsumption(): totFillBits=%d, qcOut->totFillBits=%d \n", totFillBits, qcOut->totFillBits); + /* now distribute extra fillbits and alignbits */ alignBits = 7 - (qcOut->staticBits + qcOut->usedDynBits + qcOut->elementExtBits + diff --git a/libFDK/src/FDK_crc.cpp b/libFDK/src/FDK_crc.cpp index e208338..ecbddb1 100644 --- a/libFDK/src/FDK_crc.cpp +++ b/libFDK/src/FDK_crc.cpp @@ -175,10 +175,48 @@ static const USHORT crcLookup_16_12_5_0[256] = { 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0}; /** + * \brief This table defines precalculated lookup tables for crc polynom x^16 + x^14 + x^13 + x^12 + x^11 + x^5 + x^3 + x^2 + x^0. + */ +static const USHORT crcLookup_16_14_13_12_11_5_3_2_0[256] = +{ + 0x0000, 0x782f, 0xf05e, 0x8871, 0x9893, 0xe0bc, 0x68cd, 0x10e2, + 0x4909, 0x3126, 0xb957, 0xc178, 0xd19a, 0xa9b5, 0x21c4, 0x59eb, + 0x9212, 0xea3d, 0x624c, 0x1a63, 0x0a81, 0x72ae, 0xfadf, 0x82f0, + 0xdb1b, 0xa334, 0x2b45, 0x536a, 0x4388, 0x3ba7, 0xb3d6, 0xcbf9, + 0x5c0b, 0x2424, 0xac55, 0xd47a, 0xc498, 0xbcb7, 0x34c6, 0x4ce9, + 0x1502, 0x6d2d, 0xe55c, 0x9d73, 0x8d91, 0xf5be, 0x7dcf, 0x05e0, + 0xce19, 0xb636, 0x3e47, 0x4668, 0x568a, 0x2ea5, 0xa6d4, 0xdefb, + 0x8710, 0xff3f, 0x774e, 0x0f61, 0x1f83, 0x67ac, 0xefdd, 0x97f2, + 0xb816, 0xc039, 0x4848, 0x3067, 0x2085, 0x58aa, 0xd0db, 0xa8f4, + 0xf11f, 0x8930, 0x0141, 0x796e, 0x698c, 0x11a3, 0x99d2, 0xe1fd, + 0x2a04, 0x522b, 0xda5a, 0xa275, 0xb297, 0xcab8, 0x42c9, 0x3ae6, + 0x630d, 0x1b22, 0x9353, 0xeb7c, 0xfb9e, 0x83b1, 0x0bc0, 0x73ef, + 0xe41d, 0x9c32, 0x1443, 0x6c6c, 0x7c8e, 0x04a1, 0x8cd0, 0xf4ff, + 0xad14, 0xd53b, 0x5d4a, 0x2565, 0x3587, 0x4da8, 0xc5d9, 0xbdf6, + 0x760f, 0x0e20, 0x8651, 0xfe7e, 0xee9c, 0x96b3, 0x1ec2, 0x66ed, + 0x3f06, 0x4729, 0xcf58, 0xb777, 0xa795, 0xdfba, 0x57cb, 0x2fe4, + 0x0803, 0x702c, 0xf85d, 0x8072, 0x9090, 0xe8bf, 0x60ce, 0x18e1, + 0x410a, 0x3925, 0xb154, 0xc97b, 0xd999, 0xa1b6, 0x29c7, 0x51e8, + 0x9a11, 0xe23e, 0x6a4f, 0x1260, 0x0282, 0x7aad, 0xf2dc, 0x8af3, + 0xd318, 0xab37, 0x2346, 0x5b69, 0x4b8b, 0x33a4, 0xbbd5, 0xc3fa, + 0x5408, 0x2c27, 0xa456, 0xdc79, 0xcc9b, 0xb4b4, 0x3cc5, 0x44ea, + 0x1d01, 0x652e, 0xed5f, 0x9570, 0x8592, 0xfdbd, 0x75cc, 0x0de3, + 0xc61a, 0xbe35, 0x3644, 0x4e6b, 0x5e89, 0x26a6, 0xaed7, 0xd6f8, + 0x8f13, 0xf73c, 0x7f4d, 0x0762, 0x1780, 0x6faf, 0xe7de, 0x9ff1, + 0xb015, 0xc83a, 0x404b, 0x3864, 0x2886, 0x50a9, 0xd8d8, 0xa0f7, + 0xf91c, 0x8133, 0x0942, 0x716d, 0x618f, 0x19a0, 0x91d1, 0xe9fe, + 0x2207, 0x5a28, 0xd259, 0xaa76, 0xba94, 0xc2bb, 0x4aca, 0x32e5, + 0x6b0e, 0x1321, 0x9b50, 0xe37f, 0xf39d, 0x8bb2, 0x03c3, 0x7bec, + 0xec1e, 0x9431, 0x1c40, 0x646f, 0x748d, 0x0ca2, 0x84d3, 0xfcfc, + 0xa517, 0xdd38, 0x5549, 0x2d66, 0x3d84, 0x45ab, 0xcdda, 0xb5f5, + 0x7e0c, 0x0623, 0x8e52, 0xf67d, 0xe69f, 0x9eb0, 0x16c1, 0x6eee, + 0x3705, 0x4f2a, 0xc75b, 0xbf74, 0xaf96, 0xd7b9, 0x5fc8, 0x27e7, +}; + +/** * \brief This table defines precalculated lookup tables for crc polynom x^16 * + x^15 + x^5 + x^0. */ - static const USHORT crcLookup_16_15_5_0[256] = { 0x0000, 0x8021, 0x8063, 0x0042, 0x80e7, 0x00c6, 0x0084, 0x80a5, 0x81ef, 0x01ce, 0x018c, 0x81ad, 0x0108, 0x8129, 0x816b, 0x014a, 0x83ff, 0x03de, @@ -228,6 +266,10 @@ static void crcCalc(HANDLE_FDK_CRCINFO hCrcInfo, HANDLE_FDK_BITSTREAM hBs, void FDKcrcInit(HANDLE_FDK_CRCINFO hCrcInfo, const UINT crcPoly, const UINT crcStartValue, const UINT crcLen) { /* crc polynom example: + DAB+ FireCode: + x^16 + x^14 + x^13 + x^12 + x^11 + x^5 + x^3 + x^2 + x^0 + (1) 0111 1000 0010 1101 -> 0x782d + x^16 + x^15 + x^5 + x^0 (1) 1000 0000 0010 0001 -> 0x8021 x^16 + x^15 + x^2 + x^0 (1) 1000 0000 0000 0101 -> 0x8005 x^16 + x^12 + x^5 + x^0 (1) 0001 0000 0010 0001 -> 0x1021 @@ -254,6 +296,9 @@ void FDKcrcInit(HANDLE_FDK_CRCINFO hCrcInfo, const UINT crcPoly, case 0x1021: hCrcInfo->pCrcLookup = crcLookup_16_12_5_0; break; + case 0x782d: + hCrcInfo->pCrcLookup = crcLookup_16_14_13_12_11_5_3_2_0; + break; case 0x001d: default: /* no lookup table */ @@ -406,6 +451,7 @@ static inline INT calcCrc_Bytes(USHORT *const pCrc, const USHORT *pCrcLookup, } *pCrc = crc; /* update crc value */ + //fprintf(stderr, "\n\n crc[%d]=%04x\n", i, crc); return (nBytes); } @@ -475,5 +521,6 @@ static void crcCalc(HANDLE_FDK_CRCINFO hCrcInfo, HANDLE_FDK_BITSTREAM hBs, } } + //fprintf(stderr, "\n\n crc=%04x\n", crc); hCrcInfo->crcValue = crc; } diff --git a/libFDK/src/FDK_tools_rom.cpp b/libFDK/src/FDK_tools_rom.cpp index 0095878..e9e1206 100644 --- a/libFDK/src/FDK_tools_rom.cpp +++ b/libFDK/src/FDK_tools_rom.cpp @@ -7137,6 +7137,9 @@ const element_list_t *getBitstreamElementList(AUDIO_OBJECT_TYPE aot, case AOT_AAC_LC: case AOT_SBR: case AOT_PS: + case AOT_DABPLUS_AAC_LC: + case AOT_DABPLUS_SBR: + case AOT_DABPLUS_PS: FDK_ASSERT(epConfig == -1); if (elFlags & AC_EL_GA_CCE) { return &node_aac_cce; diff --git a/libFDK/src/mdct.cpp b/libFDK/src/mdct.cpp index d697cfb..f5aa284 100644 --- a/libFDK/src/mdct.cpp +++ b/libFDK/src/mdct.cpp @@ -285,6 +285,9 @@ void imdct_gain(FIXP_DBL *pGain_m, int *pGain_e, int tl) { log2_tl = DFRACT_BITS - 1 - fNormz((FIXP_DBL)tl); gain_e += -log2_tl; + FDK_ASSERT(log2_tl - 2 >= 0); + FDK_ASSERT(log2_tl - 2 < 8*sizeof(int)); + /* Detect non-radix 2 transform length and add amplitude compensation factor which cannot be included into the exponent above */ switch ((tl) >> (log2_tl - 2)) { diff --git a/libMpegTPEnc/src/tpenc_dab.cpp b/libMpegTPEnc/src/tpenc_dab.cpp new file mode 100644 index 0000000..202fecf --- /dev/null +++ b/libMpegTPEnc/src/tpenc_dab.cpp @@ -0,0 +1,467 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +� Copyright 1995 - 2012 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 +----------------------------------------------------------------------------------------------------------- */ + +/******************************** MPEG Audio Encoder ************************** + + Initial author: serge + contents/description: DAB Transport Headers support + +******************************************************************************/ +#include <stdio.h> +#include "FDK_audio.h" +#include "tpenc_dab.h" + + +#include "tpenc_lib.h" +#include "tpenc_asc.h" + +#include "common_fix.h" + +int dabWrite_CrcStartReg( + HANDLE_DAB pDab, /*!< pointer to dab stucture */ + HANDLE_FDK_BITSTREAM hBs, /*!< handle to current bit buffer structure */ + int mBits /*!< number of bits in crc region */ + ) +{ + //fprintf(stderr, "dabWrite_CrcStartReg(%p): bits in crc region=%d\n", hBs, mBits); + return ( FDKcrcStartReg(&pDab->crcInfo2, hBs, mBits) ); +} + +void dabWrite_CrcEndReg( + HANDLE_DAB pDab, /*!< pointer to dab crc info stucture */ + HANDLE_FDK_BITSTREAM hBs, /*!< handle to current bit buffer structure */ + int reg /*!< crc region */ + ) +{ + //fprintf(stderr, "dabWrite_CrcEndReg(%p): crc region=%d\n", hBs, reg); + FDKcrcEndReg(&pDab->crcInfo2, hBs, reg); +} + +int dabWrite_GetHeaderBits( HANDLE_DAB hDab ) +{ + int bits = 0; + + if (hDab->currentBlock == 0) { + /* Static and variable header bits */ + bits += 16; //header_firecode 16 + bits += 8; //rfa=1, dac_rate=1, sbr_flag=1, aac_channel_mode=1, ps_flag=1, mpeg_surround_config=3 + bits += 12 * hDab->num_raw_blocks; //au_start[1...num_aus] 12 bit AU start position markers + + //4 byte alignment + if (hDab->dac_rate == 0 || hDab->sbr_flag == 0) + bits+=4; + //16sbr => 16 + 5 + 3 + 12*(2-1) => 36 => 40 bits 5 + //24sbr => 16 + 5 + 3 + 12*(3-1) => 48 ok 6 + //32sbr => 16 + 5 + 3 + 12*(4-1) => 60 => 64 bits 8 + //48sbr => 16 + 5 + 3 + 12*(6-1) => 84 => 88 bits 11 + } + + /* Add raw data block CRC bits. Not really part of the header, put they cause bit overhead to be accounted. */ + bits += 16; + + + return bits; +} + + +int dabWrite_CountTotalBitDemandHeader( HANDLE_DAB hDab, unsigned int streamDataLength ) +{ + //fprintf(stderr, "streamDataLength=%d (%d bytes)\n", streamDataLength, streamDataLength >> 3); + return dabWrite_GetHeaderBits(hDab); +} + + +INT dabWrite_Init(HANDLE_DAB hDab, CODER_CONFIG *config) +{ + /* Sanity checks */ + if((int)config->aot > 4 + || (int)config->aot < 1 ) { + return -1; + } + + /* Sanity checks DAB-specific */ + if ( !(config->nSubFrames == 2 && config->samplingRate == 16000 && (config->flags & CC_SBR)) && + !(config->nSubFrames == 3 && config->samplingRate == 24000 && (config->flags & CC_SBR)) && + !(config->nSubFrames == 4 && config->samplingRate == 32000) && + !(config->nSubFrames == 6 && config->samplingRate == 48000)) { + return -1; + } + + hDab->dac_rate = 0; + hDab->aac_channel_mode=0; + hDab->sbr_flag = 0; + hDab->ps_flag = 0; + hDab->mpeg_surround_config=0; + hDab->subchannels_num=config->bitRate/8000; + + + if(config->samplingRate == 24000 || config->samplingRate == 48000) + hDab->dac_rate = 1; + + if (config->extAOT==AOT_SBR || config->extAOT == AOT_PS) + hDab->sbr_flag = 1; + + if(config->extAOT == AOT_PS) + hDab->ps_flag = 1; + + + if(config->channelMode == MODE_2) + hDab->aac_channel_mode = 1; + + //fprintf(stderr, "hDab->dac_rate=%d\n", hDab->dac_rate); + //fprintf(stderr, "hDab->sbr_flag=%d\n", hDab->sbr_flag); + //fprintf(stderr, "hDab->ps_flag=%d\n", hDab->ps_flag); + //fprintf(stderr, "hDab->aac_channel_mode=%d\n", hDab->aac_channel_mode); + //fprintf(stderr, "hDab->subchannels_num=%d\n", hDab->subchannels_num); + //fprintf(stderr, "cc->nSubFrames=%d\n", config->nSubFrames); + + hDab->num_raw_blocks=config->nSubFrames-1; /* 0 means 1 raw data block */ + + FDKcrcInit(&hDab->crcInfo, 0x1021, 0xFFFF, 16); + FDKcrcInit(&hDab->crcFire, 0x782d, 0, 16); + FDKcrcInit(&hDab->crcInfo2, 0x8005, 0xFFFF, 16); + + hDab->currentBlock = 0; + hDab->headerBits = dabWrite_GetHeaderBits(hDab); + + return 0; +} + +int dabWrite_EncodeHeader(HANDLE_DAB hDab, + HANDLE_FDK_BITSTREAM hBitStream, + int buffer_fullness, + int frame_length) +{ + INT crcIndex = 0; + + + FDK_ASSERT(((frame_length+hDab->headerBits)/8)<0x2000); /*13 bit*/ + FDK_ASSERT(buffer_fullness<0x800); /* 11 bit */ + + FDKcrcReset(&hDab->crcInfo); + + +// fprintf(stderr, "dabWrite_EncodeHeader() hDab->currentBlock=%d, frame_length=%d, buffer_fullness=%d\n", +// hDab->currentBlock, frame_length, buffer_fullness); + +// if (hDab->currentBlock == 0) { +// //hDab->subFrameStartPrev=dabWrite_GetHeaderBits(hDab); +// fprintf(stderr, "header bits[%d] [%d]\n", hDab->subFrameStartPrev, hDab->subFrameStartPrev >> 3); +// FDKresetBitbuffer(hBitStream, BS_WRITER); +// } + + //hDab->subFrameStartBit = FDKgetValidBits(hBitStream); +// fprintf(stderr, "dabWrite_EncodeHeader() hDab->subFrameStartBit=%d [%d]\n", hDab->subFrameStartBit, hDab->subFrameStartBit >> 3); + + //hDab->subFrameStartBit = FDKgetValidBits(hBitStream); + /* Skip new header if this is raw data block 1..n */ + if (hDab->currentBlock == 0) + { + FDKresetBitbuffer(hBitStream, BS_WRITER); +// fprintf(stderr, "dabWrite_EncodeHeader() after FDKresetBitbuffer=%d [%d]\n", FDKgetValidBits(hBitStream), FDKgetValidBits(hBitStream) >> 3); + + /* fixed header */ + FDKwriteBits(hBitStream, 0, 16); //header_firecode + FDKwriteBits(hBitStream, 0, 1); //rfa + FDKwriteBits(hBitStream, hDab->dac_rate, 1); + FDKwriteBits(hBitStream, hDab->sbr_flag, 1); + FDKwriteBits(hBitStream, hDab->aac_channel_mode, 1); + FDKwriteBits(hBitStream, hDab->ps_flag, 1); + FDKwriteBits(hBitStream, hDab->mpeg_surround_config, 3); + /* variable header */ + int i; + for(i=0; i<hDab->num_raw_blocks; i++) + FDKwriteBits(hBitStream, 0, 12); + /* padding */ + if (hDab->dac_rate == 0 || hDab->sbr_flag == 0) { + FDKwriteBits(hBitStream, 0, 4); + } + } /* End of DAB header */ + + hDab->subFrameStartBit = FDKgetValidBits(hBitStream); + FDK_ASSERT(FDKgetValidBits(hBitStream) % 8 == 0); //only aligned header + +// fprintf(stderr, "dabWrite_EncodeHeader() FDKgetValidBits(hBitStream)=%d [%d]\n", FDKgetValidBits(hBitStream), FDKgetValidBits(hBitStream) >> 3); + return 0; +} + +int dabWrite_writeExtensionFillPayload(HANDLE_FDK_BITSTREAM hBitStream, int extPayloadBits) +{ +#define EXT_TYPE_BITS ( 4 ) +#define DATA_EL_VERSION_BITS ( 4 ) +#define FILL_NIBBLE_BITS ( 4 ) + +#define EXT_TYPE_BITS ( 4 ) +#define DATA_EL_VERSION_BITS ( 4 ) +#define FILL_NIBBLE_BITS ( 4 ) + + INT extBitsUsed = 0; + INT extPayloadType = EXT_FIL; + //fprintf(stderr, "FDKaacEnc_writeExtensionPayload() extPayloadType=%d\n", extPayloadType); + if (extPayloadBits >= EXT_TYPE_BITS) + { + UCHAR fillByte = 0x00; /* for EXT_FIL and EXT_FILL_DATA */ + + if (hBitStream != NULL) { + FDKwriteBits(hBitStream, extPayloadType, EXT_TYPE_BITS); + } + extBitsUsed += EXT_TYPE_BITS; + + switch (extPayloadType) { + case EXT_FILL_DATA: + fillByte = 0xA5; + case EXT_FIL: + default: + if (hBitStream != NULL) { + int writeBits = extPayloadBits; + FDKwriteBits(hBitStream, 0x00, FILL_NIBBLE_BITS); + writeBits -= 8; /* acount for the extension type and the fill nibble */ + while (writeBits >= 8) { + FDKwriteBits(hBitStream, fillByte, 8); + writeBits -= 8; + } + } + extBitsUsed += FILL_NIBBLE_BITS + (extPayloadBits & ~0x7) - 8; + break; + } + } + + return (extBitsUsed); +} + +void dabWrite_FillRawDataBlock(HANDLE_FDK_BITSTREAM hBitStream, int payloadBits) +{ + INT extBitsUsed = 0; +#define EL_ID_BITS ( 3 ) +#define FILL_EL_COUNT_BITS ( 4 ) +#define FILL_EL_ESC_COUNT_BITS ( 8 ) +#define MAX_FILL_DATA_BYTES ( 269 ) + while (payloadBits >= (EL_ID_BITS + FILL_EL_COUNT_BITS)) { + INT cnt, esc_count=-1, alignBits=7; + + payloadBits -= EL_ID_BITS + FILL_EL_COUNT_BITS; + if (payloadBits >= 15*8) { + payloadBits -= FILL_EL_ESC_COUNT_BITS; + esc_count = 0; /* write esc_count even if cnt becomes smaller 15 */ + } + alignBits = 0; + + cnt = fixMin(MAX_FILL_DATA_BYTES, (payloadBits+alignBits)>>3); + + if (cnt >= 15) { + esc_count = cnt - 15 + 1; + } + + if (hBitStream != NULL) { + /* write bitstream */ + FDKwriteBits(hBitStream, ID_FIL, EL_ID_BITS); + if (esc_count >= 0) { + FDKwriteBits(hBitStream, 15, FILL_EL_COUNT_BITS); + FDKwriteBits(hBitStream, esc_count, FILL_EL_ESC_COUNT_BITS); + } else { + FDKwriteBits(hBitStream, cnt, FILL_EL_COUNT_BITS); + } + } + + extBitsUsed += EL_ID_BITS + FILL_EL_COUNT_BITS + ((esc_count>=0) ? FILL_EL_ESC_COUNT_BITS : 0); + + cnt = fixMin(cnt*8, payloadBits); /* convert back to bits */ +#if 0 + extBitsUsed += FDKaacEnc_writeExtensionPayload( hBitStream, + pExtension->type, + pExtension->pPayload, + cnt ); +#else + extBitsUsed += dabWrite_writeExtensionFillPayload(hBitStream, cnt); +#endif + payloadBits -= cnt; + } +} + +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); + } + + /* Write FireCode */ + if (hDab->currentBlock == hDab->num_raw_blocks) { + FDKinitBitStream(&bsWriter, hBs->hBitBuf.Buffer, hBs->hBitBuf.bufSize, 0, BS_WRITER); + FDKpushFor(&bsWriter, 16); + + FDKcrcReset(&hDab->crcFire); + crcIndex = FDKcrcStartReg(&hDab->crcFire, &bsWriter, 72); + FDKpushFor(&bsWriter, 9*8); //9bytes + FDKcrcEndReg(&hDab->crcFire, &bsWriter, crcIndex); + + crcData = FDKcrcGetCRC(&hDab->crcFire); + //fprintf(stderr, "Firecode: %04x\n", crcData); + + FDKinitBitStream(&bsWriter, hBs->hBitBuf.Buffer, hBs->hBitBuf.bufSize, 0, BS_WRITER); + FDKwriteBits(&bsWriter, crcData, 16); + FDKsyncCache(&bsWriter); + } + + if (hDab->currentBlock == 0) + *pBits += hDab->headerBits; + else + *pBits += 16; + + *pBits += writeBits + 3; //size: ID_END + alignment + + /* Correct *pBits to reflect the amount of bits of the current subframe */ + *pBits -= hDab->subFrameStartBit; + /* Fixup CRC bits, since they come after each raw data block */ + + hDab->currentBlock++; + //fprintf(stderr, "dabWrite_EndRawDataBlock() *pBits=%d (%d)\n", *pBits, *pBits >> 3); +} + diff --git a/libMpegTPEnc/src/tpenc_dab.h b/libMpegTPEnc/src/tpenc_dab.h new file mode 100644 index 0000000..17b83c6 --- /dev/null +++ b/libMpegTPEnc/src/tpenc_dab.h @@ -0,0 +1,217 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +� Copyright 1995 - 2012 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 +----------------------------------------------------------------------------------------------------------- */ + +/******************************** MPEG Audio Encoder ************************** + + Initial author: serge + contents/description: DAB Transport writer + +******************************************************************************/ + +#ifndef TPENC_DAB_H +#define TPENC_DAB_H + + + +#include "tp_data.h" + +#include "FDK_crc.h" + +typedef struct { + USHORT frame_length; + UCHAR dac_rate; + UCHAR aac_channel_mode; + UCHAR sbr_flag; + UCHAR ps_flag; + UCHAR mpeg_surround_config; + UCHAR num_raw_blocks; + UCHAR BufferFullnesStartFlag; + int subchannels_num; + int headerBits; /*!< Header bit demand for the current raw data block */ + int currentBlock; /*!< Index of current raw data block */ + int subFrameStartBit; /*!< Bit position where the current raw data block begins */ + //int subFrameStartPrev; /*!< Bit position where the previous raw data block begins */ + int crcIndex; + FDK_CRCINFO crcInfo; + FDK_CRCINFO crcFire; + FDK_CRCINFO crcInfo2; + USHORT tab[256]; +} STRUCT_DAB; + +typedef STRUCT_DAB *HANDLE_DAB; + +/** + * \brief Initialize DAB data structure + * + * \param hDab DAB data handle + * \param config a valid CODER_CONFIG struct from where the required + * information for the DAB header is extrated from + * + * \return 0 in case of success. + */ +INT dabWrite_Init( + HANDLE_DAB hDab, + CODER_CONFIG *config + ); + +/** + * \brief Get the total bit overhead caused by DAB + * + * \hDab handle to DAB data + * + * \return Amount of additional bits required for the current raw data block + */ +int dabWrite_GetHeaderBits( HANDLE_DAB hDab ); +int dabWrite_CountTotalBitDemandHeader( HANDLE_DAB hDab, unsigned int streamDataLength ); + +/** + * \brief Write an DAB header into the given bitstream. May not write a header + * in case of multiple raw data blocks. + * + * \param hDab DAB data handle + * \param hBitStream bitstream handle into which the DAB may be written into + * \param buffer_fullness the buffer fullness value for the DAB header + * \param the current raw data block length + * + * \return 0 in case of success. + */ +INT dabWrite_EncodeHeader( + HANDLE_DAB hDab, + HANDLE_FDK_BITSTREAM hBitStream, + int bufferFullness, + int frame_length + ); +/** + * \brief Finish a DAB raw data block + * + * \param hDab DAB data handle + * \param hBs bitstream handle into which the DAB may be written into + * \param pBits a pointer to a integer holding the current bitstream buffer bit count, + * which is corrected to the current raw data block boundary. + * + */ +void dabWrite_EndRawDataBlock( + HANDLE_DAB hDab, + HANDLE_FDK_BITSTREAM hBs, + int *bits + ); + + +/** + * \brief Start CRC region with a maximum number of bits + * If mBits is positive zero padding will be used for CRC calculation, if there + * are less than mBits bits available. + * If mBits is negative no zero padding is done. + * If mBits is zero the memory for the buffer is allocated dynamically, the + * number of bits is not limited. + * + * \param pDab DAB data handle + * \param hBs bitstream handle of which the CRC region ends + * \param mBits limit of number of bits to be considered for the requested CRC region + * + * \return ID for the created region, -1 in case of an error + */ +int dabWrite_CrcStartReg( + HANDLE_DAB pDab, + HANDLE_FDK_BITSTREAM hBs, + int mBits + ); + +/** + * \brief Ends CRC region identified by reg + * + * \param pDab DAB data handle + * \param hBs bitstream handle of which the CRC region ends + * \param reg a CRC region ID returned previously by dabWrite_CrcStartReg() + */ +void dabWrite_CrcEndReg( + HANDLE_DAB pDab, + HANDLE_FDK_BITSTREAM hBs, + int reg + ); + + + + +#endif /* TPENC_DAB_H */ + diff --git a/libMpegTPEnc/src/tpenc_lib.cpp b/libMpegTPEnc/src/tpenc_lib.cpp index a8567b9..3578871 100644 --- a/libMpegTPEnc/src/tpenc_lib.cpp +++ b/libMpegTPEnc/src/tpenc_lib.cpp @@ -113,6 +113,8 @@ amm-info@iis.fraunhofer.de #include "tpenc_adif.h" +#include "tpenc_dab.h" + #include "tpenc_latm.h" typedef struct { @@ -137,6 +139,8 @@ struct TRANSPORTENC { ADIF_INFO adif; + STRUCT_DAB dab; + LATM_STREAM latm; RAWPACKETS_INFO raw; @@ -214,6 +218,7 @@ static INT getPceRepetitionRate(const CHANNEL_MODE channelMode, } case TT_MP4_LOAS: /* PCE in ASC if chChonfig==0 */ case TT_MP4_LATM_MCP1: /* PCE in ASC if chChonfig==0 */ + case TT_DABPLUS: default: pceFrameCounter = -1; /* no PCE in raw_data_block */ } @@ -232,6 +237,7 @@ static INT getPceRepetitionRate(const CHANNEL_MODE channelMode, case TT_MP4_RAW: pceFrameCounter = headerPeriod; break; + case TT_DABPLUS: default: pceFrameCounter = -1; /* no PCE in raw_data_block */ } /* switch transportFmt */ @@ -294,6 +300,18 @@ TRANSPORTENC_ERROR transportEnc_Init(HANDLE_TRANSPORTENC hTpEnc, } 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: { @@ -409,6 +427,17 @@ TRANSPORTENC_ERROR transportEnc_WriteAccessUnit(HANDLE_TRANSPORTENC hTp, 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: @@ -477,6 +506,9 @@ TRANSPORTENC_ERROR transportEnc_EndAccessUnit(HANDLE_TRANSPORTENC hTp, case TT_MP4_ADTS: adtsWrite_EndRawDataBlock(&hTp->writer.adts, &hTp->bitStream, bits); break; + case TT_DABPLUS: + dabWrite_EndRawDataBlock(&hTp->writer.dab, &hTp->bitStream, bits); + break; case TT_MP4_ADIF: /* Substract ADIF header from AU bits, not to be considered. */ *bits -= adifWrite_GetHeaderBits(&hTp->writer.adif); @@ -513,6 +545,14 @@ TRANSPORTENC_ERROR transportEnc_GetFrame(HANDLE_TRANSPORTENC hTpEnc, *nbytes = 0; } break; + case TT_DABPLUS: + if (hTpEnc->writer.dab.currentBlock >= hTpEnc->writer.dab.num_raw_blocks+1) { + *nbytes = (FDKgetValidBits(hBs) + 7)>>3; + hTpEnc->writer.dab.currentBlock = 0; + } else { + *nbytes = 0; + } + break; case TT_MP4_ADIF: FDK_ASSERT((INT)FDKgetValidBits(hBs) >= 0); *nbytes = (FDKgetValidBits(hBs) + 7) >> 3; @@ -550,6 +590,9 @@ INT transportEnc_GetStaticBits(HANDLE_TRANSPORTENC hTp, int auBits) { case TT_MP4_ADTS: nbits = adtsWrite_GetHeaderBits(&hTp->writer.adts); break; + case TT_DABPLUS: + nbits = dabWrite_CountTotalBitDemandHeader(&hTp->writer.dab, auBits); + break; case TT_MP4_LOAS: case TT_MP4_LATM_MCP0: case TT_MP4_LATM_MCP1: @@ -584,6 +627,9 @@ int transportEnc_CrcStartReg(HANDLE_TRANSPORTENC hTpEnc, int mBits) { crcReg = adtsWrite_CrcStartReg(&hTpEnc->writer.adts, &hTpEnc->bitStream, mBits); break; + case TT_DABPLUS: + crcReg = dabWrite_CrcStartReg(&hTpEnc->writer.dab, &hTpEnc->bitStream, mBits); + break; default: break; } @@ -596,6 +642,9 @@ void transportEnc_CrcEndReg(HANDLE_TRANSPORTENC hTpEnc, int reg) { case TT_MP4_ADTS: adtsWrite_CrcEndReg(&hTpEnc->writer.adts, &hTpEnc->bitStream, reg); break; + case TT_DABPLUS: + dabWrite_CrcEndReg(&hTpEnc->writer.dab, &hTpEnc->bitStream, reg); + break; default: break; } @@ -657,7 +706,7 @@ TRANSPORTENC_ERROR transportEnc_GetLibInfo(LIB_INFO *info) { /* Set flags */ info->flags = - 0 | CAPF_ADIF | CAPF_ADTS | CAPF_LATM | CAPF_LOAS | CAPF_RAWPACKETS; + 0 | CAPF_ADIF | CAPF_ADTS | CAPF_LATM | CAPF_LOAS | CAPF_RAWPACKETS | CAPF_DAB_AAC; return TRANSPORTENC_OK; } diff --git a/libSBRenc/src/env_est.cpp b/libSBRenc/src/env_est.cpp index 0eb8425..4af561b 100644 --- a/libSBRenc/src/env_est.cpp +++ b/libSBRenc/src/env_est.cpp @@ -1151,6 +1151,7 @@ void FDKsbrEnc_extractSbrEnvelope2( SBR_STEREO_MODE stereoMode = h_con->stereoMode; int nChannels = h_con->nChannels; + FDK_ASSERT(nChannels <= MAX_NUM_CHANNELS); const int *v_tuning; static const int v_tuningHEAAC[6] = {0, 2, 4, 0, 0, 0}; diff --git a/libSBRenc/src/sbr_encoder.cpp b/libSBRenc/src/sbr_encoder.cpp index df9e996..26257a1 100644 --- a/libSBRenc/src/sbr_encoder.cpp +++ b/libSBRenc/src/sbr_encoder.cpp @@ -2096,7 +2096,7 @@ INT sbrEncoder_Init(HANDLE_SBR_ENCODER hSbrEncoder, *downSampleFactor = 2; } - if (aot == AOT_PS) { + if (aot == AOT_PS || aot == AOT_DABPLUS_PS) { usePs = 1; } if (aot == AOT_ER_AAC_ELD) { diff --git a/libSYS/include/FDK_audio.h b/libSYS/include/FDK_audio.h index 0e440c9..d69c008 100644 --- a/libSYS/include/FDK_audio.h +++ b/libSYS/include/FDK_audio.h @@ -145,7 +145,8 @@ typedef enum { TT_MP4_LOAS = 10, /**< Audio Sync Stream. */ - TT_DRM = 12 /**< Digital Radio Mondial (DRM30/DRM+) bitstream format. */ + TT_DRM = 12, /**< Digital Radio Mondial (DRM30/DRM+) bitstream format. */ + TT_DABPLUS = 13 /**< Digital Audio Broadcastong (DAB+) superframes bitstream format. */ } TRANSPORT_TYPE; @@ -205,6 +206,11 @@ typedef enum { AOT_SAOC = 43, /**< SAOC */ AOT_LD_MPEGS = 44, /**< Low Delay MPEG Surround */ + AOT_DABPLUS_AAC_LC = 135, /**< Virtual AOT for DAB plus AAC-LC */ + AOT_DABPLUS_SBR = 136, /**< Virtual AOT for DAB plus HE-AAC */ + AOT_DABPLUS_PS = 137, /**< Virtual AOT for DAB plus HE-AAC v2 */ + + /* Pseudo AOTs */ AOT_MP2_AAC_LC = 129, /**< Virtual AOT MP2 Low Complexity profile */ AOT_MP2_SBR = 132, /**< Virtual AOT MP2 Low Complexity Profile with SBR */ @@ -626,6 +632,14 @@ typedef enum { #define CAPF_SBR_HBEHQ \ 0x00000100 /**< Support flag for HQ HBE */ +/* DAB capability flags */ +#define CAPF_DAB_MP2 0x00000001 /**< Support flag for Layer2 DAB. */ +#define CAPF_DAB_AAC 0x00000002 /**< Support flag for DAB+ (HE-AAC v2). */ +#define CAPF_DAB_PAD 0x00000004 /**< Support flag for PAD extraction. */ +#define CAPF_DAB_DRC 0x00000008 /**< Support flag for Dynamic Range Control. */ +#define CAPF_DAB_SURROUND 0x00000010 /**< Support flag for DAB Surround (MPS). */ + + /* PCM utils capability flags */ #define CAPF_DMX_BLIND \ 0x00000001 /**< Support flag for blind downmixing. */ |