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 /libMpegTPEnc/src/tpenc_dab.cpp | |
parent | 651ff34d8d35fb6a3b75471d54b271852f5924cc (diff) | |
download | fdk-aac-bdfafd471e3c7c240b5c78e8d1233ce61f17c296.tar.gz fdk-aac-bdfafd471e3c7c240b5c78e8d1233ce61f17c296.tar.bz2 fdk-aac-bdfafd471e3c7c240b5c78e8d1233ce61f17c296.zip |
Add DAB+ support
Diffstat (limited to 'libMpegTPEnc/src/tpenc_dab.cpp')
-rw-r--r-- | libMpegTPEnc/src/tpenc_dab.cpp | 467 |
1 files changed, 467 insertions, 0 deletions
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); +} + |