2 /* -----------------------------------------------------------------------------------------------------------
3 Software License for The Fraunhofer FDK AAC Codec Library for Android
5 © Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
9 The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements
10 the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio.
11 This FDK AAC Codec software is intended to be used on a wide variety of Android devices.
13 AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual
14 audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by
15 independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part
16 of the MPEG specifications.
18 Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer)
19 may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners
20 individually for the purpose of encoding or decoding bit streams in products that are compliant with
21 the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license
22 these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec
23 software may already be covered under those patent licenses when it is used for those licensed purposes only.
25 Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality,
26 are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional
27 applications information and documentation.
31 Redistribution and use in source and binary forms, with or without modification, are permitted without
32 payment of copyright license fees provided that you satisfy the following conditions:
34 You must retain the complete text of this software license in redistributions of the FDK AAC Codec or
35 your modifications thereto in source code form.
37 You must retain the complete text of this software license in the documentation and/or other materials
38 provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form.
39 You must make available free of charge copies of the complete source code of the FDK AAC Codec and your
40 modifications thereto to recipients of copies in binary form.
42 The name of Fraunhofer may not be used to endorse or promote products derived from this library without
43 prior written permission.
45 You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec
46 software or your modifications thereto.
48 Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software
49 and the date of any change. For modified versions of the FDK AAC Codec, the term
50 "Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term
51 "Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android."
55 NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer,
56 ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with
57 respect to this software.
59 You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized
60 by appropriate patent licenses.
64 This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors
65 "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties
66 of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
67 CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages,
68 including but not limited to procurement of substitute goods or services; loss of use, data, or profits,
69 or business interruption, however caused and on any theory of liability, whether in contract, strict
70 liability, or tort (including negligence), arising in any way out of the use of this software, even if
71 advised of the possibility of such damage.
73 5. CONTACT INFORMATION
75 Fraunhofer Institute for Integrated Circuits IIS
76 Attention: Audio and Multimedia Departments - FDK AAC LL
78 91058 Erlangen, Germany
80 www.iis.fraunhofer.de/amm
81 amm-info@iis.fraunhofer.de
82 ----------------------------------------------------------------------------------------------------------- */
84 /************************** MPEG-4 Transport Encoder ************************
86 Author(s): Manuel Jander
87 Description: MPEG Transport encode
89 ******************************************************************************/
91 #include "tpenc_lib.h"
96 #define MODULE_NAME "transportEnc"
98 #include "tpenc_asc.h"
99 #include "conv_string.h"
101 #include "tpenc_adts.h"
103 #include "tpenc_adif.h"
105 #include "tpenc_latm.h"
118 TRANSPORT_TYPE transportFmt
; /*!< MPEG4 transport type. */
120 FDK_BITSTREAM bitStream
;
124 INT pceFrameCounter
; /*!< Indicates frame period when PCE must be written in raw_data_block.
125 -1 means not to write a PCE in raw_dat_block. */
139 CSTpCallBacks callbacks
;
142 typedef struct _TRANSPORTENC_STRUCT TRANSPORTENC_STRUCT
;
149 C_ALLOC_MEM(Ram_TransportEncoder
, TRANSPORTENC
, 1)
151 TRANSPORTENC_ERROR
transportEnc_Open( HANDLE_TRANSPORTENC
*phTpEnc
)
153 HANDLE_TRANSPORTENC hTpEnc
;
155 if ( phTpEnc
== NULL
){
156 return TRANSPORTENC_INVALID_PARAMETER
;
159 hTpEnc
= GetRam_TransportEncoder(0);
161 if ( hTpEnc
== NULL
) {
162 return TRANSPORTENC_NO_MEM
;
166 return TRANSPORTENC_OK
;
170 * \brief Get frame period of PCE in raw_data_block.
172 * - Write PCE only if necessary. PCE can be part of the ASC if chConfig==0 whererfore
173 * no additonal PCE will be written in raw_data_block.
174 * - A matrixMixdown coefficient can only be written if chConfig is 5.0 or 5.1.
175 * - The PCE repetition rate in raw_data_block can be controlled via headerPeriod parameter.
177 * \param channelConfig Channel Configuration derived from Channel Mode
178 * \param transportFmt Format of the transport to be written.
179 * \param headerPeriod Chosen PCE frame repetition rate.
180 * \param matrixMixdownA Indicates if a valid Matrix Mixdown coefficient is available.
182 * \return PCE frame repetition rate. -1 means no PCE present in raw_data_block.
184 static INT
getPceRepetitionRate(
185 const int channelConfig
,
186 const TRANSPORT_TYPE transportFmt
,
187 const int headerPeriod
,
188 const int matrixMixdownA
191 INT pceFrameCounter
= -1; /* variable to be returned */
193 if (headerPeriod
>0) {
194 switch ( channelConfig
) {
196 switch (transportFmt
) {
198 case TT_MP4_LATM_MCP0
:
200 pceFrameCounter
= headerPeriod
;
202 case TT_MP4_ADIF
: /* ADIF header comprises PCE */
203 case TT_MP4_LOAS
: /* PCE in ASC if chChonfig==0 */
204 case TT_MP4_LATM_MCP1
: /* PCE in ASC if chChonfig==0 */
205 case TT_DRM
: /* PCE not allowed in DRM */
207 pceFrameCounter
= -1; /* no PCE in raw_data_block */
210 case 5: /* MODE_1_2_2 */
211 case 6: /* MODE_1_2_2_1 */
212 /* matrixMixdownCoefficient can only be written if 5.0 and 5.1 config present. */
213 if (matrixMixdownA
!=0) {
214 switch (transportFmt
) {
215 case TT_MP4_ADIF
: /* ADIF header comprises PCE */
217 case TT_MP4_LOAS
: /* no PCE in ASC because chConfig!=0 */
218 case TT_MP4_LATM_MCP1
: /* no PCE in ASC because chConfig!=0 */
219 case TT_MP4_LATM_MCP0
:
221 pceFrameCounter
= headerPeriod
;
223 case TT_DRM
: /* PCE not allowed in DRM */
225 pceFrameCounter
= -1; /* no PCE in raw_data_block */
226 } /* switch transportFmt */
227 } /* if matrixMixdownA!=0 */
230 pceFrameCounter
= -1; /* no PCE in raw_data_block */
231 } /* switch getChannelConfig() */
232 } /* if headerPeriod>0 */
234 pceFrameCounter
= -1; /* no PCE in raw_data_block */
237 return pceFrameCounter
;
240 TRANSPORTENC_ERROR
transportEnc_Init(
241 HANDLE_TRANSPORTENC hTpEnc
,
244 TRANSPORT_TYPE transportFmt
,
245 CODER_CONFIG
*cconfig
,
249 /* Copy configuration structure */
250 FDKmemcpy(&hTpEnc
->config
, cconfig
, sizeof(CODER_CONFIG
));
252 /* Init transportEnc struct. */
253 hTpEnc
->transportFmt
= transportFmt
;
255 hTpEnc
->bsBuffer
= bsBuffer
;
256 hTpEnc
->bsBufferSize
= bsBufferSize
;
258 FDKinitBitStream(&hTpEnc
->bitStream
, hTpEnc
->bsBuffer
, hTpEnc
->bsBufferSize
, 0, BS_WRITER
);
260 switch (transportFmt
) {
264 if ( (hTpEnc
->config
.aot
!= AOT_AAC_LC
)
265 ||(hTpEnc
->config
.samplesPerFrame
!= 1024))
267 return TRANSPORTENC_INVALID_PARAMETER
;
269 hTpEnc
->writer
.adif
.headerWritten
= 0;
270 hTpEnc
->writer
.adif
.samplingRate
= hTpEnc
->config
.samplingRate
;
271 hTpEnc
->writer
.adif
.bitRate
= hTpEnc
->config
.bitRate
;
272 hTpEnc
->writer
.adif
.profile
= ((int)hTpEnc
->config
.aot
) - 1;
273 hTpEnc
->writer
.adif
.cm
= hTpEnc
->config
.channelMode
;
274 hTpEnc
->writer
.adif
.bVariableRate
= 0;
275 hTpEnc
->writer
.adif
.instanceTag
= 0;
280 if ( ( hTpEnc
->config
.aot
!= AOT_AAC_LC
)
281 ||(hTpEnc
->config
.samplesPerFrame
!= 1024) )
283 return TRANSPORTENC_INVALID_PARAMETER
;
285 if ( adtsWrite_Init(&hTpEnc
->writer
.adts
, &hTpEnc
->config
) != 0) {
286 return TRANSPORTENC_INVALID_PARAMETER
;
291 case TT_MP4_LATM_MCP0
:
292 case TT_MP4_LATM_MCP1
:
294 TRANSPORTENC_ERROR error
;
296 error
= transportEnc_Latm_Init(
297 &hTpEnc
->writer
.latm
,
300 flags
& TP_FLAG_LATM_AMV
,
304 if (error
!= TRANSPORTENC_OK
) {
311 hTpEnc
->writer
.raw
.curSubFrame
= 0;
312 hTpEnc
->writer
.raw
.nSubFrames
= hTpEnc
->config
.nSubFrames
;
318 return TRANSPORTENC_INVALID_PARAMETER
;
321 /* pceFrameCounter indicates if PCE must be written in raw_data_block. */
322 hTpEnc
->pceFrameCounter
= getPceRepetitionRate(
323 getChannelConfig(hTpEnc
->config
.channelMode
),
325 hTpEnc
->config
.headerPeriod
,
326 hTpEnc
->config
.matrixMixdownA
);
328 return TRANSPORTENC_OK
;
331 HANDLE_FDK_BITSTREAM
transportEnc_GetBitstream( HANDLE_TRANSPORTENC hTp
)
333 return &hTp
->bitStream
;
336 int transportEnc_RegisterSbrCallback( HANDLE_TRANSPORTENC hTpEnc
, const cbSbr_t cbSbr
, void* user_data
)
338 if (hTpEnc
== NULL
) {
341 hTpEnc
->callbacks
.cbSbr
= cbSbr
;
342 hTpEnc
->callbacks
.cbSbrData
= user_data
;
347 TRANSPORTENC_ERROR
transportEnc_WriteAccessUnit(
348 HANDLE_TRANSPORTENC hTp
,
354 TRANSPORTENC_ERROR err
= TRANSPORTENC_OK
;
357 return TRANSPORTENC_INVALID_PARAMETER
;
359 HANDLE_FDK_BITSTREAM hBs
= &hTp
->bitStream
;
361 /* In case of writing PCE in raw_data_block frameUsedBits must be adapted. */
362 if (hTp
->pceFrameCounter
>=hTp
->config
.headerPeriod
) {
363 frameUsedBits
+= transportEnc_GetPCEBits(hTp
->config
.channelMode
, hTp
->config
.matrixMixdownA
, 3); /* Consider 3 bits ID signalling in alignment */
366 switch (hTp
->transportFmt
) {
368 FDKinitBitStream(&hTp
->bitStream
, hTp
->bsBuffer
, hTp
->bsBufferSize
, 0, BS_WRITER
);
369 adifWrite_EncodeHeader(
376 bufferFullness
/= ncc
; /* Number of Considered Channels */
377 bufferFullness
/= 32;
378 bufferFullness
= FDKmin(0x7FF, bufferFullness
); /* Signal variable rate */
379 adtsWrite_EncodeHeader(
387 case TT_MP4_LATM_MCP0
:
388 case TT_MP4_LATM_MCP1
:
389 bufferFullness
/= ncc
; /* Number of Considered Channels */
390 bufferFullness
/= 32;
391 bufferFullness
= FDKmin(0xFF, bufferFullness
); /* Signal variable rate */
392 transportEnc_LatmWrite(
401 if (hTp
->writer
.raw
.curSubFrame
>= hTp
->writer
.raw
.nSubFrames
) {
402 hTp
->writer
.raw
.curSubFrame
= 0;
403 FDKinitBitStream(&hTp
->bitStream
, hTp
->bsBuffer
, hTp
->bsBufferSize
, 0, BS_WRITER
);
405 hTp
->writer
.raw
.prevBits
= FDKgetValidBits(hBs
);
408 err
= TRANSPORTENC_UNSUPPORTED_FORMAT
;
412 /* Write PCE in raw_data_block if required */
413 if (hTp
->pceFrameCounter
>=hTp
->config
.headerPeriod
) {
415 /* Align inside PCE with repsect to the first bit of the raw_data_block() */
416 UINT alignAnchor
= FDKgetValidBits(&hTp
->bitStream
);
418 /* Write PCE element ID bits */
419 FDKwriteBits(&hTp
->bitStream
, ID_PCE
, 3);
421 if ( (hTp
->transportFmt
==TT_MP4_ADTS
) && !hTp
->writer
.adts
.protection_absent
) {
422 crcIndex
= adtsWrite_CrcStartReg(&hTp
->writer
.adts
, &hTp
->bitStream
, 0);
425 /* Write PCE as first raw_data_block element */
426 transportEnc_writePCE(&hTp
->bitStream
, hTp
->config
.channelMode
, hTp
->config
.samplingRate
, 0, 1, hTp
->config
.matrixMixdownA
, (hTp
->config
.flags
&CC_PSEUDO_SURROUND
)?1:0, alignAnchor
);
428 if ( (hTp
->transportFmt
==TT_MP4_ADTS
) && !hTp
->writer
.adts
.protection_absent
) {
429 adtsWrite_CrcEndReg(&hTp
->writer
.adts
, &hTp
->bitStream
, crcIndex
);
431 hTp
->pceFrameCounter
= 0; /* reset pce frame counter */
434 if (hTp
->pceFrameCounter
!=-1) {
435 hTp
->pceFrameCounter
++; /* Update pceFrameCounter only if PCE writing is active. */
442 TRANSPORTENC_ERROR
transportEnc_EndAccessUnit(HANDLE_TRANSPORTENC hTp
, int *bits
)
444 switch (hTp
->transportFmt
) {
445 case TT_MP4_LATM_MCP0
:
446 case TT_MP4_LATM_MCP1
:
448 transportEnc_LatmAdjustSubframeBits(&hTp
->writer
.latm
, bits
);
451 adtsWrite_EndRawDataBlock(&hTp
->writer
.adts
, &hTp
->bitStream
, bits
);
454 /* Substract ADIF header from AU bits, not to be considered. */
455 *bits
-= adifWrite_GetHeaderBits(&hTp
->writer
.adif
);
456 hTp
->writer
.adif
.headerWritten
= 1;
459 *bits
-= hTp
->writer
.raw
.prevBits
;
465 return TRANSPORTENC_OK
;
468 TRANSPORTENC_ERROR
transportEnc_GetFrame(HANDLE_TRANSPORTENC hTpEnc
, int *nbytes
)
470 HANDLE_FDK_BITSTREAM hBs
= &hTpEnc
->bitStream
;
472 switch (hTpEnc
->transportFmt
) {
473 case TT_MP4_LATM_MCP0
:
474 case TT_MP4_LATM_MCP1
:
476 *nbytes
= hTpEnc
->bsBufferSize
;
477 transportEnc_LatmGetFrame(&hTpEnc
->writer
.latm
, hBs
, nbytes
);
480 if (hTpEnc
->writer
.adts
.currentBlock
>= hTpEnc
->writer
.adts
.num_raw_blocks
+1) {
481 *nbytes
= (FDKgetValidBits(hBs
) + 7)>>3;
482 hTpEnc
->writer
.adts
.currentBlock
= 0;
488 FDK_ASSERT((INT
)FDKgetValidBits(hBs
) >= 0);
489 *nbytes
= (FDKgetValidBits(hBs
) + 7)>>3;
493 hTpEnc
->writer
.raw
.curSubFrame
++;
494 *nbytes
= ((FDKgetValidBits(hBs
)-hTpEnc
->writer
.raw
.prevBits
) + 7)>>3;
500 return TRANSPORTENC_OK
;
503 INT
transportEnc_GetStaticBits( HANDLE_TRANSPORTENC hTp
, int auBits
)
505 INT nbits
= 0, nPceBits
= 0;
507 /* Write PCE within raw_data_block in transport lib. */
508 if (hTp
->pceFrameCounter
>=hTp
->config
.headerPeriod
) {
509 nPceBits
= transportEnc_GetPCEBits(hTp
->config
.channelMode
, hTp
->config
.matrixMixdownA
, 3); /* Consider 3 bits ID signalling in alignment */
510 auBits
+= nPceBits
; /* Adapt required raw_data_block bit consumtpion for AU length information e.g. in LATM/LOAS configuration. */
513 switch (hTp
->transportFmt
) {
516 nbits
= 0; /* Do not consider the ADIF header into the total bitrate */
519 nbits
= adtsWrite_GetHeaderBits(&hTp
->writer
.adts
);
522 case TT_MP4_LATM_MCP0
:
523 case TT_MP4_LATM_MCP1
:
524 nbits
= transportEnc_LatmCountTotalBitDemandHeader( &hTp
->writer
.latm
, auBits
);
531 /* PCE is written in the transport library therefore the bit consumption is part of the transport static bits. */
537 void transportEnc_Close(HANDLE_TRANSPORTENC
*phTp
)
542 FreeRam_TransportEncoder(phTp
);
547 int transportEnc_CrcStartReg(HANDLE_TRANSPORTENC hTpEnc
, int mBits
)
551 switch (hTpEnc
->transportFmt
) {
553 crcReg
= adtsWrite_CrcStartReg(&hTpEnc
->writer
.adts
, &hTpEnc
->bitStream
, mBits
);
562 void transportEnc_CrcEndReg(HANDLE_TRANSPORTENC hTpEnc
, int reg
)
564 switch (hTpEnc
->transportFmt
) {
566 adtsWrite_CrcEndReg(&hTpEnc
->writer
.adts
, &hTpEnc
->bitStream
, reg
);
574 TRANSPORTENC_ERROR
transportEnc_GetConf(HANDLE_TRANSPORTENC hTpEnc
,
576 FDK_BITSTREAM
*dataBuffer
,
579 TRANSPORTENC_ERROR tpErr
= TRANSPORTENC_OK
;
580 HANDLE_LATM_STREAM hLatmConfig
= &hTpEnc
->writer
.latm
;
582 *confType
= 0; /* set confType variable to default */
584 /* write StreamMuxConfig or AudioSpecificConfig depending on format used */
585 switch (hTpEnc
->transportFmt
)
587 case TT_MP4_LATM_MCP0
:
588 case TT_MP4_LATM_MCP1
:
590 tpErr
= CreateStreamMuxConfig(hLatmConfig
, dataBuffer
, 0, &hTpEnc
->callbacks
);
591 *confType
= 1; /* config is SMC */
594 if (transportEnc_writeASC(dataBuffer
, cc
, &hTpEnc
->callbacks
) != 0) {
595 tpErr
= TRANSPORTENC_UNKOWN_ERROR
;
603 TRANSPORTENC_ERROR
transportEnc_GetLibInfo( LIB_INFO
*info
)
608 return TRANSPORTENC_INVALID_PARAMETER
;
610 /* search for next free tab */
611 for (i
= 0; i
< FDK_MODULE_LAST
; i
++) {
612 if (info
[i
].module_id
== FDK_NONE
) break;
614 if (i
== FDK_MODULE_LAST
) {
615 return TRANSPORTENC_UNKOWN_ERROR
;
619 info
->module_id
= FDK_TPENC
;
620 info
->version
= LIB_VERSION(TP_LIB_VL0
, TP_LIB_VL1
, TP_LIB_VL2
);
621 LIB_VERSION_STRING(info
);
622 info
->build_date
= __DATE__
;
623 info
->build_time
= __TIME__
;
624 info
->title
= TP_LIB_TITLE
;
635 return TRANSPORTENC_OK
;