diff options
| -rw-r--r-- | Makefile.am | 3 | ||||
| -rw-r--r-- | README.md | 27 | ||||
| -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 | 108 | ||||
| -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, 1210 insertions, 36 deletions
| diff --git a/Makefile.am b/Makefile.am index 06b9b60..292a6ac 100644 --- a/Makefile.am +++ b/Makefile.am @@ -165,7 +165,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..c114e87 --- /dev/null +++ b/README.md @@ -0,0 +1,27 @@ +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](https://github.com/Opendigitalradio/ODR-AudioEnc) + +See http://www.opendigitalradio.org for more + +Branches in this repository +=========================== + +The dabplus branch points to a version that builds `libfdk-aac.so.1`. +The dabplus2 branch points to a version that builds `libfdk-aac.so.2`. + +Installation +============ + +Make sure you have installed git, build-essential and automake, otherwise install them with `sudo apt-get install git build-essential automake`. + +    $ git clone https://github.com/Opendigitalradio/fdk-aac.git +    $ cd fdk-aac/ +    $ ./bootstrap +    $ ./configure +    $ make +    $ sudo make install 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 902ba11..c21daf4 100644 --- a/libAACenc/include/aacenc_lib.h +++ b/libAACenc/include/aacenc_lib.h @@ -1318,6 +1318,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). @@ -1481,6 +1482,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 1af8a2e..42755ab 100644 --- a/libAACenc/src/aacenc.cpp +++ b/libAACenc/src/aacenc.cpp @@ -188,6 +188,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;  } @@ -472,6 +473,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( @@ -495,6 +526,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 ee7f918..212afdf 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: @@ -490,11 +495,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; @@ -543,9 +554,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; @@ -823,6 +852,7 @@ static INT aacEncoder_LimitBitrate(const HANDLE_TRANSPORTENC hTpEnc,          bitRate);    } +  //fprintf(stderr, "aacEncoder_LimitBitrate(): bitRate=%d\n", bitRate);    return bitRate;  } @@ -938,6 +968,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; @@ -1169,7 +1214,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.    */    { @@ -1586,7 +1647,7 @@ AACENC_ERROR aacEncOpen(HANDLE_AACENCODER *phAacEncoder, const UINT encModules,    hAacEncoder->outBufferInBytes =        1 << (DFRACT_BITS - CntLeadingZeros(fixMax(                                1, ((1) * hAacEncoder->nMaxAacChannels * 6144) >> -                                     3))); /* buffer has to be 2^n */ +                                     2))); /* buffer has to be 2^n */    if (NULL == (hAacEncoder->outBuffer = (UCHAR *)FDKcalloc(                     hAacEncoder->outBufferInBytes, sizeof(UCHAR)))) {      err = AACENC_MEMORY_ERROR; @@ -2102,7 +2163,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 */ @@ -2127,6 +2188,7 @@ 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; @@ -2134,6 +2196,7 @@ AACENC_ERROR aacEncoder_SetParam(const HANDLE_AACENCODER hAacEncoder,              FDK_FALLTHROUGH;            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; @@ -2141,6 +2204,7 @@ AACENC_ERROR aacEncoder_SetParam(const HANDLE_AACENCODER hAacEncoder,              FDK_FALLTHROUGH;            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))) { @@ -2172,6 +2236,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; @@ -2258,6 +2324,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: @@ -2300,17 +2367,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;          } @@ -2360,7 +2428,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 957e821..512d596 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" @@ -1197,6 +1198,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]; @@ -1283,20 +1301,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);    } @@ -1314,9 +1352,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 9a42550..b4c38af 100644 --- a/libAACenc/src/qc_main.cpp +++ b/libAACenc/src/qc_main.cpp @@ -474,6 +474,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, @@ -1357,6 +1358,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 0062b27..c864fa1 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 77c19b5..d241979 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; @@ -215,6 +219,7 @@ static INT getPceRepetitionRate(const CHANNEL_MODE channelMode,              FDK_FALLTHROUGH;            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 */          } @@ -233,6 +238,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 */ @@ -295,6 +301,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: { @@ -410,6 +428,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: @@ -478,6 +507,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); @@ -514,6 +546,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; @@ -551,6 +591,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: @@ -585,6 +628,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;    } @@ -597,6 +643,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;    } @@ -658,7 +707,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 e7eea37..3936d88 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 c3da072..048c734 100644 --- a/libSBRenc/src/sbr_encoder.cpp +++ b/libSBRenc/src/sbr_encoder.cpp @@ -2095,7 +2095,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.             */ | 
