/src/aac/libAACenc/src/metadata_main.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* ----------------------------------------------------------------------------- |
2 | | Software License for The Fraunhofer FDK AAC Codec Library for Android |
3 | | |
4 | | © Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten |
5 | | Forschung e.V. All rights reserved. |
6 | | |
7 | | 1. INTRODUCTION |
8 | | The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software |
9 | | that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding |
10 | | scheme for digital audio. This FDK AAC Codec software is intended to be used on |
11 | | a wide variety of Android devices. |
12 | | |
13 | | AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient |
14 | | general perceptual audio codecs. AAC-ELD is considered the best-performing |
15 | | full-bandwidth communications codec by independent studies and is widely |
16 | | deployed. AAC has been standardized by ISO and IEC as part of the MPEG |
17 | | specifications. |
18 | | |
19 | | Patent licenses for necessary patent claims for the FDK AAC Codec (including |
20 | | those of Fraunhofer) may be obtained through Via Licensing |
21 | | (www.vialicensing.com) or through the respective patent owners individually for |
22 | | the purpose of encoding or decoding bit streams in products that are compliant |
23 | | with the ISO/IEC MPEG audio standards. Please note that most manufacturers of |
24 | | Android devices already license these patent claims through Via Licensing or |
25 | | directly from the patent owners, and therefore FDK AAC Codec software may |
26 | | already be covered under those patent licenses when it is used for those |
27 | | licensed purposes only. |
28 | | |
29 | | Commercially-licensed AAC software libraries, including floating-point versions |
30 | | with enhanced sound quality, are also available from Fraunhofer. Users are |
31 | | encouraged to check the Fraunhofer website for additional applications |
32 | | information and documentation. |
33 | | |
34 | | 2. COPYRIGHT LICENSE |
35 | | |
36 | | Redistribution and use in source and binary forms, with or without modification, |
37 | | are permitted without payment of copyright license fees provided that you |
38 | | satisfy the following conditions: |
39 | | |
40 | | You must retain the complete text of this software license in redistributions of |
41 | | the FDK AAC Codec or your modifications thereto in source code form. |
42 | | |
43 | | You must retain the complete text of this software license in the documentation |
44 | | and/or other materials provided with redistributions of the FDK AAC Codec or |
45 | | your modifications thereto in binary form. You must make available free of |
46 | | charge copies of the complete source code of the FDK AAC Codec and your |
47 | | modifications thereto to recipients of copies in binary form. |
48 | | |
49 | | The name of Fraunhofer may not be used to endorse or promote products derived |
50 | | from this library without prior written permission. |
51 | | |
52 | | You may not charge copyright license fees for anyone to use, copy or distribute |
53 | | the FDK AAC Codec software or your modifications thereto. |
54 | | |
55 | | Your modified versions of the FDK AAC Codec must carry prominent notices stating |
56 | | that you changed the software and the date of any change. For modified versions |
57 | | of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" |
58 | | must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK |
59 | | AAC Codec Library for Android." |
60 | | |
61 | | 3. NO PATENT LICENSE |
62 | | |
63 | | NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without |
64 | | limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. |
65 | | Fraunhofer provides no warranty of patent non-infringement with respect to this |
66 | | software. |
67 | | |
68 | | You may use this FDK AAC Codec software or modifications thereto only for |
69 | | purposes that are authorized by appropriate patent licenses. |
70 | | |
71 | | 4. DISCLAIMER |
72 | | |
73 | | This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright |
74 | | holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, |
75 | | including but not limited to the implied warranties of merchantability and |
76 | | fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR |
77 | | CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, |
78 | | or consequential damages, including but not limited to procurement of substitute |
79 | | goods or services; loss of use, data, or profits, or business interruption, |
80 | | however caused and on any theory of liability, whether in contract, strict |
81 | | liability, or tort (including negligence), arising in any way out of the use of |
82 | | this software, even if advised of the possibility of such damage. |
83 | | |
84 | | 5. CONTACT INFORMATION |
85 | | |
86 | | Fraunhofer Institute for Integrated Circuits IIS |
87 | | Attention: Audio and Multimedia Departments - FDK AAC LL |
88 | | Am Wolfsmantel 33 |
89 | | 91058 Erlangen, Germany |
90 | | |
91 | | www.iis.fraunhofer.de/amm |
92 | | amm-info@iis.fraunhofer.de |
93 | | ----------------------------------------------------------------------------- */ |
94 | | |
95 | | /**************************** AAC encoder library ****************************** |
96 | | |
97 | | Author(s): V. Bacigalupo |
98 | | |
99 | | Description: Metadata Encoder library interface functions |
100 | | |
101 | | *******************************************************************************/ |
102 | | |
103 | | #include "metadata_main.h" |
104 | | #include "metadata_compressor.h" |
105 | | #include "FDK_bitstream.h" |
106 | | #include "FDK_audio.h" |
107 | | #include "genericStds.h" |
108 | | |
109 | | /*----------------- defines ----------------------*/ |
110 | | #define MAX_DRC_BANDS (1 << 4) |
111 | 0 | #define MAX_DRC_FRAMELEN (2 * 1024) |
112 | 0 | #define MAX_DELAY_FRAMES (3) |
113 | | |
114 | | /*--------------- structure definitions --------------------*/ |
115 | | |
116 | | typedef struct AAC_METADATA { |
117 | | /* MPEG: Dynamic Range Control */ |
118 | | struct { |
119 | | UCHAR prog_ref_level_present; |
120 | | SCHAR prog_ref_level; |
121 | | |
122 | | UCHAR dyn_rng_sgn[MAX_DRC_BANDS]; |
123 | | UCHAR dyn_rng_ctl[MAX_DRC_BANDS]; |
124 | | |
125 | | UCHAR drc_bands_present; |
126 | | UCHAR drc_band_incr; |
127 | | UCHAR drc_band_top[MAX_DRC_BANDS]; |
128 | | UCHAR drc_interpolation_scheme; |
129 | | AACENC_METADATA_DRC_PROFILE drc_profile; |
130 | | INT drc_TargetRefLevel; /* used for Limiter */ |
131 | | |
132 | | /* excluded channels */ |
133 | | UCHAR excluded_chns_present; |
134 | | UCHAR exclude_mask[2]; /* MAX_NUMBER_CHANNELS/8 */ |
135 | | } mpegDrc; |
136 | | |
137 | | /* ETSI: addtl ancillary data */ |
138 | | struct { |
139 | | /* Heavy Compression */ |
140 | | UCHAR compression_on; /* flag, if compression value should be written */ |
141 | | UCHAR compression_value; /* compression value */ |
142 | | AACENC_METADATA_DRC_PROFILE comp_profile; |
143 | | INT comp_TargetRefLevel; /* used for Limiter */ |
144 | | INT timecode_coarse_status; |
145 | | INT timecode_fine_status; |
146 | | |
147 | | UCHAR extAncDataStatus; |
148 | | |
149 | | struct { |
150 | | UCHAR ext_downmix_lvl_status; |
151 | | UCHAR ext_downmix_gain_status; |
152 | | UCHAR ext_lfe_downmix_status; |
153 | | UCHAR |
154 | | ext_dmix_a_idx; /* extended downmix level (0..7, according to table) |
155 | | */ |
156 | | UCHAR |
157 | | ext_dmix_b_idx; /* extended downmix level (0..7, according to table) |
158 | | */ |
159 | | UCHAR dmx_gain_5_sgn; |
160 | | UCHAR dmx_gain_5_idx; |
161 | | UCHAR dmx_gain_2_sgn; |
162 | | UCHAR dmx_gain_2_idx; |
163 | | UCHAR ext_dmix_lfe_idx; /* extended downmix level for lfe (0..15, |
164 | | according to table) */ |
165 | | |
166 | | } extAncData; |
167 | | |
168 | | } etsiAncData; |
169 | | |
170 | | SCHAR centerMixLevel; /* center downmix level (0...7, according to table) */ |
171 | | SCHAR |
172 | | surroundMixLevel; /* surround downmix level (0...7, according to table) */ |
173 | | UCHAR WritePCEMixDwnIdx; /* flag */ |
174 | | UCHAR DmxLvl_On; /* flag */ |
175 | | |
176 | | UCHAR dolbySurroundMode; |
177 | | UCHAR drcPresentationMode; |
178 | | |
179 | | UCHAR |
180 | | metadataMode; /* indicate meta data mode in current frame (delay line) */ |
181 | | |
182 | | } AAC_METADATA; |
183 | | |
184 | | typedef struct FDK_METADATA_ENCODER { |
185 | | INT metadataMode; |
186 | | HDRC_COMP hDrcComp; |
187 | | AACENC_MetaData submittedMetaData; |
188 | | |
189 | | INT nAudioDataDelay; /* Additional delay to round up to next frame border (in |
190 | | samples) */ |
191 | | INT nMetaDataDelay; /* Meta data delay (in frames) */ |
192 | | INT nChannels; |
193 | | CHANNEL_MODE channelMode; |
194 | | |
195 | | INT_PCM* pAudioDelayBuffer; |
196 | | |
197 | | AAC_METADATA metaDataBuffer[MAX_DELAY_FRAMES]; |
198 | | INT metaDataDelayIdx; |
199 | | |
200 | | UCHAR drcInfoPayload[12]; |
201 | | UCHAR drcDsePayload[8]; |
202 | | |
203 | | INT matrix_mixdown_idx; |
204 | | |
205 | | AACENC_EXT_PAYLOAD exPayload[2]; |
206 | | INT nExtensions; |
207 | | |
208 | | UINT maxChannels; /* Maximum number of audio channels to be supported. */ |
209 | | |
210 | | INT finalizeMetaData; /* Delay switch off by one frame and write default |
211 | | configuration to finalize the metadata setup. */ |
212 | | INT initializeMetaData; /* Fill up delay line with first meta data info. This |
213 | | is required to have meta data already in first |
214 | | frame. */ |
215 | | } FDK_METADATA_ENCODER; |
216 | | |
217 | | /*---------------- constants -----------------------*/ |
218 | | static const AACENC_MetaData defaultMetaDataSetup = { |
219 | | AACENC_METADATA_DRC_NONE, /* drc_profile */ |
220 | | AACENC_METADATA_DRC_NOT_PRESENT, /* comp_profile */ |
221 | | -(31 << 16), /* drc_TargetRefLevel */ |
222 | | -(23 << 16), /* comp_TargetRefLevel */ |
223 | | 0, /* prog_ref_level_present */ |
224 | | -(23 << 16), /* prog_ref_level */ |
225 | | 0, /* PCE_mixdown_idx_present */ |
226 | | 0, /* ETSI_DmxLvl_present */ |
227 | | 0, /* centerMixLevel */ |
228 | | 0, /* surroundMixLevel */ |
229 | | 0, /* dolbySurroundMode */ |
230 | | 0, /* drcPresentationMode */ |
231 | | {0, 0, 0, 0, 0, 0, 0, 0, 0} /* ExtMetaData */ |
232 | | }; |
233 | | |
234 | | static const FIXP_DBL dmxTable[8] = { |
235 | | ((FIXP_DBL)MAXVAL_DBL), FL2FXCONST_DBL(0.841f), FL2FXCONST_DBL(0.707f), |
236 | | FL2FXCONST_DBL(0.596f), FL2FXCONST_DBL(0.500f), FL2FXCONST_DBL(0.422f), |
237 | | FL2FXCONST_DBL(0.355f), FL2FXCONST_DBL(0.000f)}; |
238 | | |
239 | | #define FL2DMXLFE(a) FL2FXCONST_DBL((a) / (1 << LFE_LEV_SCALE)) |
240 | | static const FIXP_DBL dmxLfeTable[16] = { |
241 | | FL2DMXLFE(3.162f), FL2DMXLFE(2.000f), FL2DMXLFE(1.679f), FL2DMXLFE(1.413f), |
242 | | FL2DMXLFE(1.189f), FL2DMXLFE(1.000f), FL2DMXLFE(0.841f), FL2DMXLFE(0.707f), |
243 | | FL2DMXLFE(0.596f), FL2DMXLFE(0.500f), FL2DMXLFE(0.316f), FL2DMXLFE(0.178f), |
244 | | FL2DMXLFE(0.100f), FL2DMXLFE(0.032f), FL2DMXLFE(0.010f), FL2DMXLFE(0.000f)}; |
245 | | |
246 | | static const UCHAR surmix2matrix_mixdown_idx[8] = {0, 0, 0, 1, 1, 2, 2, 3}; |
247 | | |
248 | | /*--------------- function declarations --------------------*/ |
249 | | static FDK_METADATA_ERROR WriteMetadataPayload( |
250 | | const HANDLE_FDK_METADATA_ENCODER hMetaData, |
251 | | const AAC_METADATA* const pMetadata); |
252 | | |
253 | | static INT WriteDynamicRangeInfoPayload(const AAC_METADATA* const pMetadata, |
254 | | UCHAR* const pExtensionPayload); |
255 | | |
256 | | static INT WriteEtsiAncillaryDataPayload(const AAC_METADATA* const pMetadata, |
257 | | UCHAR* const pExtensionPayload); |
258 | | |
259 | | static FDK_METADATA_ERROR CompensateAudioDelay( |
260 | | HANDLE_FDK_METADATA_ENCODER hMetaDataEnc, INT_PCM* const pAudioSamples, |
261 | | const UINT audioSamplesBufSize, const INT nAudioSamples); |
262 | | |
263 | | static FDK_METADATA_ERROR LoadSubmittedMetadata( |
264 | | const AACENC_MetaData* const hMetadata, const INT nChannels, |
265 | | const INT metadataMode, AAC_METADATA* const pAacMetaData); |
266 | | |
267 | | static FDK_METADATA_ERROR ProcessCompressor(AAC_METADATA* pMetadata, |
268 | | HDRC_COMP hDrcComp, |
269 | | const INT_PCM* const pSamples, |
270 | | const UINT samplesBufSize, |
271 | | const INT nSamples); |
272 | | |
273 | | /*------------- function definitions ----------------*/ |
274 | | |
275 | 0 | static DRC_PROFILE convertProfile(AACENC_METADATA_DRC_PROFILE aacProfile) { |
276 | 0 | DRC_PROFILE drcProfile = DRC_NONE; |
277 | |
|
278 | 0 | switch (aacProfile) { |
279 | 0 | case AACENC_METADATA_DRC_NONE: |
280 | 0 | drcProfile = DRC_NONE; |
281 | 0 | break; |
282 | 0 | case AACENC_METADATA_DRC_FILMSTANDARD: |
283 | 0 | drcProfile = DRC_FILMSTANDARD; |
284 | 0 | break; |
285 | 0 | case AACENC_METADATA_DRC_FILMLIGHT: |
286 | 0 | drcProfile = DRC_FILMLIGHT; |
287 | 0 | break; |
288 | 0 | case AACENC_METADATA_DRC_MUSICSTANDARD: |
289 | 0 | drcProfile = DRC_MUSICSTANDARD; |
290 | 0 | break; |
291 | 0 | case AACENC_METADATA_DRC_MUSICLIGHT: |
292 | 0 | drcProfile = DRC_MUSICLIGHT; |
293 | 0 | break; |
294 | 0 | case AACENC_METADATA_DRC_SPEECH: |
295 | 0 | drcProfile = DRC_SPEECH; |
296 | 0 | break; |
297 | 0 | case AACENC_METADATA_DRC_NOT_PRESENT: |
298 | 0 | drcProfile = DRC_NOT_PRESENT; |
299 | 0 | break; |
300 | 0 | default: |
301 | 0 | drcProfile = DRC_NONE; |
302 | 0 | break; |
303 | 0 | } |
304 | 0 | return drcProfile; |
305 | 0 | } |
306 | | |
307 | | /* convert dialog normalization to program reference level */ |
308 | | /* NOTE: this only is correct, if the decoder target level is set to -31dB for |
309 | | * line mode / -20dB for RF mode */ |
310 | 0 | static UCHAR dialnorm2progreflvl(const INT d) { |
311 | 0 | return ((UCHAR)fMax(0, fMin((-d + (1 << 13)) >> 14, 127))); |
312 | 0 | } |
313 | | |
314 | | /* convert program reference level to dialog normalization */ |
315 | 0 | static INT progreflvl2dialnorm(const UCHAR p) { |
316 | 0 | return -((INT)(p << (16 - 2))); |
317 | 0 | } |
318 | | |
319 | | /* encode downmix levels to Downmixing_levels_MPEG4 */ |
320 | 0 | static SCHAR encodeDmxLvls(const SCHAR cmixlev, const SCHAR surmixlev) { |
321 | 0 | SCHAR dmxLvls = 0; |
322 | 0 | dmxLvls |= 0x80 | (cmixlev << 4); /* center_mix_level_on */ |
323 | 0 | dmxLvls |= 0x08 | surmixlev; /* surround_mix_level_on */ |
324 | |
|
325 | 0 | return dmxLvls; |
326 | 0 | } |
327 | | |
328 | | /* encode AAC DRC gain (ISO/IEC 14496-3:2005 4.5.2.7) */ |
329 | | static void encodeDynrng(INT gain, UCHAR* const dyn_rng_ctl, |
330 | 0 | UCHAR* const dyn_rng_sgn) { |
331 | 0 | if (gain < 0) { |
332 | 0 | *dyn_rng_sgn = 1; |
333 | 0 | gain = -gain; |
334 | 0 | } else { |
335 | 0 | *dyn_rng_sgn = 0; |
336 | 0 | } |
337 | 0 | gain = fMin(gain, (127 << 14)); |
338 | |
|
339 | 0 | *dyn_rng_ctl = (UCHAR)((gain + (1 << 13)) >> 14); |
340 | 0 | } |
341 | | |
342 | | /* decode AAC DRC gain (ISO/IEC 14496-3:2005 4.5.2.7) */ |
343 | 0 | static INT decodeDynrng(const UCHAR dyn_rng_ctl, const UCHAR dyn_rng_sgn) { |
344 | 0 | INT tmp = ((INT)dyn_rng_ctl << (16 - 2)); |
345 | 0 | if (dyn_rng_sgn) tmp = -tmp; |
346 | |
|
347 | 0 | return tmp; |
348 | 0 | } |
349 | | |
350 | | /* encode AAC compression value (ETSI TS 101 154 page 99) */ |
351 | 0 | static UCHAR encodeCompr(INT gain) { |
352 | 0 | UCHAR x, y; |
353 | 0 | INT tmp; |
354 | | |
355 | | /* tmp = (int)((48.164f - gain) / 6.0206f * 15 + 0.5f); */ |
356 | 0 | tmp = ((3156476 - gain) * 15 + 197283) / 394566; |
357 | |
|
358 | 0 | if (tmp >= 240) { |
359 | 0 | return 0xFF; |
360 | 0 | } else if (tmp < 0) { |
361 | 0 | return 0; |
362 | 0 | } else { |
363 | 0 | x = tmp / 15; |
364 | 0 | y = tmp % 15; |
365 | 0 | } |
366 | | |
367 | 0 | return (x << 4) | y; |
368 | 0 | } |
369 | | |
370 | | /* decode AAC compression value (ETSI TS 101 154 page 99) */ |
371 | 0 | static INT decodeCompr(const UCHAR compr) { |
372 | 0 | INT gain; |
373 | 0 | SCHAR x = compr >> 4; /* 4 MSB of compr */ |
374 | 0 | UCHAR y = (compr & 0x0F); /* 4 LSB of compr */ |
375 | | |
376 | | /* gain = (INT)((48.164f - 6.0206f * x - 0.4014f * y) ); */ |
377 | 0 | gain = (INT)( |
378 | 0 | scaleValue((FIXP_DBL)(((LONG)FL2FXCONST_DBL(6.0206f / 128.f) * (8 - x) - |
379 | 0 | (LONG)FL2FXCONST_DBL(0.4014f / 128.f) * y)), |
380 | 0 | -(DFRACT_BITS - 1 - 7 - 16))); |
381 | |
|
382 | 0 | return gain; |
383 | 0 | } |
384 | | |
385 | | FDK_METADATA_ERROR FDK_MetadataEnc_Open(HANDLE_FDK_METADATA_ENCODER* phMetaData, |
386 | 0 | const UINT maxChannels) { |
387 | 0 | FDK_METADATA_ERROR err = METADATA_OK; |
388 | 0 | HANDLE_FDK_METADATA_ENCODER hMetaData = NULL; |
389 | |
|
390 | 0 | if (phMetaData == NULL) { |
391 | 0 | err = METADATA_INVALID_HANDLE; |
392 | 0 | goto bail; |
393 | 0 | } |
394 | | |
395 | | /* allocate memory */ |
396 | 0 | if (NULL == (hMetaData = (HANDLE_FDK_METADATA_ENCODER)FDKcalloc( |
397 | 0 | 1, sizeof(FDK_METADATA_ENCODER)))) { |
398 | 0 | err = METADATA_MEMORY_ERROR; |
399 | 0 | goto bail; |
400 | 0 | } |
401 | 0 | FDKmemclear(hMetaData, sizeof(FDK_METADATA_ENCODER)); |
402 | |
|
403 | 0 | if (NULL == (hMetaData->pAudioDelayBuffer = (INT_PCM*)FDKcalloc( |
404 | 0 | maxChannels * MAX_DRC_FRAMELEN, sizeof(INT_PCM)))) { |
405 | 0 | err = METADATA_MEMORY_ERROR; |
406 | 0 | goto bail; |
407 | 0 | } |
408 | 0 | FDKmemclear(hMetaData->pAudioDelayBuffer, |
409 | 0 | maxChannels * MAX_DRC_FRAMELEN * sizeof(INT_PCM)); |
410 | 0 | hMetaData->maxChannels = maxChannels; |
411 | | |
412 | | /* Allocate DRC Compressor. */ |
413 | 0 | if (FDK_DRC_Generator_Open(&hMetaData->hDrcComp) != 0) { |
414 | 0 | err = METADATA_MEMORY_ERROR; |
415 | 0 | goto bail; |
416 | 0 | } |
417 | 0 | hMetaData->channelMode = MODE_UNKNOWN; |
418 | | |
419 | | /* Return metadata instance */ |
420 | 0 | *phMetaData = hMetaData; |
421 | |
|
422 | 0 | return err; |
423 | | |
424 | 0 | bail: |
425 | 0 | FDK_MetadataEnc_Close(&hMetaData); |
426 | 0 | return err; |
427 | 0 | } |
428 | | |
429 | | FDK_METADATA_ERROR FDK_MetadataEnc_Close( |
430 | 0 | HANDLE_FDK_METADATA_ENCODER* phMetaData) { |
431 | 0 | FDK_METADATA_ERROR err = METADATA_OK; |
432 | |
|
433 | 0 | if (phMetaData == NULL) { |
434 | 0 | err = METADATA_INVALID_HANDLE; |
435 | 0 | goto bail; |
436 | 0 | } |
437 | | |
438 | 0 | if (*phMetaData != NULL) { |
439 | 0 | FDK_DRC_Generator_Close(&(*phMetaData)->hDrcComp); |
440 | 0 | FDKfree((*phMetaData)->pAudioDelayBuffer); |
441 | 0 | FDKfree(*phMetaData); |
442 | 0 | *phMetaData = NULL; |
443 | 0 | } |
444 | 0 | bail: |
445 | 0 | return err; |
446 | 0 | } |
447 | | |
448 | | FDK_METADATA_ERROR FDK_MetadataEnc_Init( |
449 | | HANDLE_FDK_METADATA_ENCODER hMetaData, const INT resetStates, |
450 | | const INT metadataMode, const INT audioDelay, const UINT frameLength, |
451 | | const UINT sampleRate, const UINT nChannels, const CHANNEL_MODE channelMode, |
452 | 0 | const CHANNEL_ORDER channelOrder) { |
453 | 0 | FDK_METADATA_ERROR err = METADATA_OK; |
454 | 0 | int i, nFrames, delay; |
455 | |
|
456 | 0 | if (hMetaData == NULL) { |
457 | 0 | err = METADATA_INVALID_HANDLE; |
458 | 0 | goto bail; |
459 | 0 | } |
460 | | |
461 | | /* Determine values for delay compensation. */ |
462 | 0 | for (nFrames = 0, delay = audioDelay - (INT)frameLength; delay > 0; |
463 | 0 | delay -= (INT)frameLength, nFrames++) |
464 | 0 | ; |
465 | |
|
466 | 0 | if ((nChannels > (8)) || (nChannels > hMetaData->maxChannels) || |
467 | 0 | ((-delay) > MAX_DRC_FRAMELEN) || nFrames >= MAX_DELAY_FRAMES) { |
468 | 0 | err = METADATA_INIT_ERROR; |
469 | 0 | goto bail; |
470 | 0 | } |
471 | | |
472 | | /* Initialize with default setup. */ |
473 | 0 | FDKmemcpy(&hMetaData->submittedMetaData, &defaultMetaDataSetup, |
474 | 0 | sizeof(AACENC_MetaData)); |
475 | |
|
476 | 0 | hMetaData->finalizeMetaData = |
477 | 0 | 0; /* finalize meta data only while on/off switching, else disabled */ |
478 | 0 | hMetaData->initializeMetaData = |
479 | 0 | 0; /* fill up meta data delay line only at a reset otherwise disabled */ |
480 | | |
481 | | /* Reset delay lines. */ |
482 | 0 | if (resetStates || (hMetaData->nAudioDataDelay != -delay) || |
483 | 0 | (hMetaData->channelMode != channelMode)) { |
484 | 0 | if (resetStates || (hMetaData->channelMode == MODE_UNKNOWN)) { |
485 | | /* clear delay buffer */ |
486 | 0 | FDKmemclear(hMetaData->pAudioDelayBuffer, |
487 | 0 | hMetaData->maxChannels * MAX_DRC_FRAMELEN * sizeof(INT_PCM)); |
488 | 0 | } else { |
489 | | /* if possible, keep static audio channels for seamless channel |
490 | | * reconfiguration */ |
491 | 0 | FDK_channelMapDescr mapDescrPrev, mapDescr; |
492 | 0 | int c, src[2] = {-1, -1}, dst[2] = {-1, -1}; |
493 | |
|
494 | 0 | FDK_chMapDescr_init(&mapDescrPrev, NULL, 0, |
495 | 0 | (channelOrder == CH_ORDER_MPEG) ? 1 : 0); |
496 | 0 | FDK_chMapDescr_init(&mapDescr, NULL, 0, |
497 | 0 | (channelOrder == CH_ORDER_MPEG) ? 1 : 0); |
498 | |
|
499 | 0 | switch (channelMode) { |
500 | 0 | case MODE_1: |
501 | 0 | if ((INT)nChannels != 2) { |
502 | | /* preserve center channel */ |
503 | 0 | src[0] = FDK_chMapDescr_getMapValue(&mapDescrPrev, 0, |
504 | 0 | hMetaData->channelMode); |
505 | 0 | dst[0] = FDK_chMapDescr_getMapValue(&mapDescr, 0, channelMode); |
506 | 0 | } |
507 | 0 | break; |
508 | 0 | case MODE_2: |
509 | 0 | case MODE_1_2: |
510 | 0 | case MODE_1_2_1: |
511 | 0 | case MODE_1_2_2: |
512 | 0 | case MODE_1_2_2_1: |
513 | 0 | if (hMetaData->nChannels >= 2) { |
514 | | /* preserve left/right channel */ |
515 | 0 | src[0] = FDK_chMapDescr_getMapValue( |
516 | 0 | &mapDescrPrev, ((hMetaData->channelMode == 2) ? 0 : 1), |
517 | 0 | hMetaData->channelMode); |
518 | 0 | src[1] = FDK_chMapDescr_getMapValue( |
519 | 0 | &mapDescrPrev, ((hMetaData->channelMode == 2) ? 1 : 2), |
520 | 0 | hMetaData->channelMode); |
521 | 0 | dst[0] = FDK_chMapDescr_getMapValue( |
522 | 0 | &mapDescr, ((channelMode == 2) ? 0 : 1), channelMode); |
523 | 0 | dst[1] = FDK_chMapDescr_getMapValue( |
524 | 0 | &mapDescr, ((channelMode == 2) ? 1 : 2), channelMode); |
525 | 0 | } |
526 | 0 | break; |
527 | 0 | default:; |
528 | 0 | } |
529 | 0 | C_ALLOC_SCRATCH_START(scratch_audioDelayBuffer, INT_PCM, (8)); |
530 | 0 | FDKmemclear(scratch_audioDelayBuffer, (8) * sizeof(INT_PCM)); |
531 | |
|
532 | 0 | i = (hMetaData->nChannels > (INT)nChannels) |
533 | 0 | ? 0 |
534 | 0 | : hMetaData->nAudioDataDelay - 1; |
535 | 0 | do { |
536 | 0 | for (c = 0; c < 2; c++) { |
537 | 0 | if (src[c] != -1 && dst[c] != -1) { |
538 | 0 | scratch_audioDelayBuffer[dst[c]] = |
539 | 0 | hMetaData->pAudioDelayBuffer[i * hMetaData->nChannels + src[c]]; |
540 | 0 | } |
541 | 0 | } |
542 | 0 | FDKmemcpy(&hMetaData->pAudioDelayBuffer[i * nChannels], |
543 | 0 | scratch_audioDelayBuffer, nChannels * sizeof(INT_PCM)); |
544 | 0 | i += (hMetaData->nChannels > (INT)nChannels) ? 1 : -1; |
545 | 0 | } while ((i < hMetaData->nAudioDataDelay) && (i >= 0)); |
546 | |
|
547 | 0 | C_ALLOC_SCRATCH_END(scratch_audioDelayBuffer, INT_PCM, (8)); |
548 | 0 | } |
549 | 0 | FDKmemclear(hMetaData->metaDataBuffer, sizeof(hMetaData->metaDataBuffer)); |
550 | 0 | hMetaData->metaDataDelayIdx = 0; |
551 | 0 | hMetaData->initializeMetaData = |
552 | 0 | 1; /* fill up delay line with first meta data info */ |
553 | 0 | } else { |
554 | | /* Enable meta data. */ |
555 | 0 | if ((hMetaData->metadataMode == 0) && (metadataMode != 0)) { |
556 | | /* disable meta data in all delay lines */ |
557 | 0 | for (i = 0; |
558 | 0 | i < (int)(sizeof(hMetaData->metaDataBuffer) / sizeof(AAC_METADATA)); |
559 | 0 | i++) { |
560 | 0 | LoadSubmittedMetadata(&hMetaData->submittedMetaData, nChannels, 0, |
561 | 0 | &hMetaData->metaDataBuffer[i]); |
562 | 0 | } |
563 | 0 | } |
564 | | |
565 | | /* Disable meta data.*/ |
566 | 0 | if ((hMetaData->metadataMode != 0) && (metadataMode == 0)) { |
567 | 0 | hMetaData->finalizeMetaData = hMetaData->metadataMode; |
568 | 0 | } |
569 | 0 | } |
570 | | |
571 | | /* Initialize delay. */ |
572 | 0 | hMetaData->nAudioDataDelay = -delay; |
573 | 0 | hMetaData->nMetaDataDelay = nFrames; |
574 | 0 | hMetaData->nChannels = nChannels; |
575 | 0 | hMetaData->channelMode = channelMode; |
576 | 0 | hMetaData->metadataMode = metadataMode; |
577 | | |
578 | | /* Initialize compressor. */ |
579 | 0 | if ((metadataMode == 1) || (metadataMode == 2)) { |
580 | 0 | if (FDK_DRC_Generator_Initialize(hMetaData->hDrcComp, DRC_NONE, DRC_NONE, |
581 | 0 | frameLength, sampleRate, channelMode, |
582 | 0 | channelOrder, 1) != 0) { |
583 | 0 | err = METADATA_INIT_ERROR; |
584 | 0 | } |
585 | 0 | } |
586 | 0 | bail: |
587 | 0 | return err; |
588 | 0 | } |
589 | | |
590 | | static FDK_METADATA_ERROR ProcessCompressor(AAC_METADATA* pMetadata, |
591 | | HDRC_COMP hDrcComp, |
592 | | const INT_PCM* const pSamples, |
593 | | const UINT samplesBufSize, |
594 | 0 | const INT nSamples) { |
595 | 0 | FDK_METADATA_ERROR err = METADATA_OK; |
596 | |
|
597 | 0 | INT dynrng, compr; |
598 | 0 | INT dmxGain5, dmxGain2; |
599 | 0 | DRC_PROFILE profileDrc; |
600 | 0 | DRC_PROFILE profileComp; |
601 | |
|
602 | 0 | if ((pMetadata == NULL) || (hDrcComp == NULL)) { |
603 | 0 | err = METADATA_INVALID_HANDLE; |
604 | 0 | return err; |
605 | 0 | } |
606 | | |
607 | 0 | profileDrc = convertProfile(pMetadata->mpegDrc.drc_profile); |
608 | 0 | profileComp = convertProfile(pMetadata->etsiAncData.comp_profile); |
609 | | |
610 | | /* first, check if profile is same as last frame |
611 | | * otherwise, update setup */ |
612 | 0 | if ((profileDrc != FDK_DRC_Generator_getDrcProfile(hDrcComp)) || |
613 | 0 | (profileComp != FDK_DRC_Generator_getCompProfile(hDrcComp))) { |
614 | 0 | FDK_DRC_Generator_setDrcProfile(hDrcComp, profileDrc, profileComp); |
615 | 0 | } |
616 | | |
617 | | /* Sanity check */ |
618 | 0 | if (profileComp == DRC_NONE) { |
619 | 0 | pMetadata->etsiAncData.compression_value = 0x80; /* to ensure no external |
620 | | values will be written |
621 | | if not configured */ |
622 | 0 | } |
623 | | |
624 | | /* in case of embedding external values, copy this now (limiter may overwrite |
625 | | * them) */ |
626 | 0 | dynrng = decodeDynrng(pMetadata->mpegDrc.dyn_rng_ctl[0], |
627 | 0 | pMetadata->mpegDrc.dyn_rng_sgn[0]); |
628 | 0 | compr = decodeCompr(pMetadata->etsiAncData.compression_value); |
629 | |
|
630 | 0 | dmxGain5 = decodeDynrng(pMetadata->etsiAncData.extAncData.dmx_gain_5_idx, |
631 | 0 | pMetadata->etsiAncData.extAncData.dmx_gain_5_sgn); |
632 | 0 | dmxGain2 = decodeDynrng(pMetadata->etsiAncData.extAncData.dmx_gain_2_idx, |
633 | 0 | pMetadata->etsiAncData.extAncData.dmx_gain_2_sgn); |
634 | | |
635 | | /* Call compressor */ |
636 | 0 | if (FDK_DRC_Generator_Calc( |
637 | 0 | hDrcComp, pSamples, samplesBufSize, |
638 | 0 | progreflvl2dialnorm(pMetadata->mpegDrc.prog_ref_level), |
639 | 0 | pMetadata->mpegDrc.drc_TargetRefLevel, |
640 | 0 | pMetadata->etsiAncData.comp_TargetRefLevel, |
641 | 0 | dmxTable[pMetadata->centerMixLevel], |
642 | 0 | dmxTable[pMetadata->surroundMixLevel], |
643 | 0 | dmxTable[pMetadata->etsiAncData.extAncData.ext_dmix_a_idx], |
644 | 0 | dmxTable[pMetadata->etsiAncData.extAncData.ext_dmix_b_idx], |
645 | 0 | pMetadata->etsiAncData.extAncData.ext_lfe_downmix_status |
646 | 0 | ? dmxLfeTable[pMetadata->etsiAncData.extAncData.ext_dmix_lfe_idx] |
647 | 0 | : (FIXP_DBL)0, |
648 | 0 | dmxGain5, dmxGain2, &dynrng, &compr) != 0) { |
649 | 0 | err = METADATA_ENCODE_ERROR; |
650 | 0 | goto bail; |
651 | 0 | } |
652 | | |
653 | | /* Write DRC values */ |
654 | 0 | pMetadata->mpegDrc.drc_band_incr = 0; |
655 | 0 | encodeDynrng(dynrng, pMetadata->mpegDrc.dyn_rng_ctl, |
656 | 0 | pMetadata->mpegDrc.dyn_rng_sgn); |
657 | 0 | pMetadata->etsiAncData.compression_value = encodeCompr(compr); |
658 | |
|
659 | 0 | bail: |
660 | 0 | return err; |
661 | 0 | } |
662 | | |
663 | | FDK_METADATA_ERROR FDK_MetadataEnc_Process( |
664 | | HANDLE_FDK_METADATA_ENCODER hMetaDataEnc, INT_PCM* const pAudioSamples, |
665 | | const UINT audioSamplesBufSize, const INT nAudioSamples, |
666 | | const AACENC_MetaData* const pMetadata, |
667 | | AACENC_EXT_PAYLOAD** ppMetaDataExtPayload, UINT* nMetaDataExtensions, |
668 | 0 | INT* matrix_mixdown_idx) { |
669 | 0 | FDK_METADATA_ERROR err = METADATA_OK; |
670 | 0 | int metaDataDelayWriteIdx, metaDataDelayReadIdx, metadataMode; |
671 | | |
672 | | /* Where to write new meta data info */ |
673 | 0 | metaDataDelayWriteIdx = hMetaDataEnc->metaDataDelayIdx; |
674 | | |
675 | | /* How to write the data */ |
676 | 0 | metadataMode = hMetaDataEnc->metadataMode; |
677 | | |
678 | | /* Compensate meta data delay. */ |
679 | 0 | hMetaDataEnc->metaDataDelayIdx++; |
680 | 0 | if (hMetaDataEnc->metaDataDelayIdx > hMetaDataEnc->nMetaDataDelay) |
681 | 0 | hMetaDataEnc->metaDataDelayIdx = 0; |
682 | | |
683 | | /* Where to read pending meta data info from. */ |
684 | 0 | metaDataDelayReadIdx = hMetaDataEnc->metaDataDelayIdx; |
685 | | |
686 | | /* Submit new data if available. */ |
687 | 0 | if (pMetadata != NULL) { |
688 | 0 | FDKmemcpy(&hMetaDataEnc->submittedMetaData, pMetadata, |
689 | 0 | sizeof(AACENC_MetaData)); |
690 | 0 | } |
691 | | |
692 | | /* Write one additional frame with default configuration of meta data. Ensure |
693 | | * defined behaviour on decoder side. */ |
694 | 0 | if ((hMetaDataEnc->finalizeMetaData != 0) && |
695 | 0 | (hMetaDataEnc->metadataMode == 0)) { |
696 | 0 | FDKmemcpy(&hMetaDataEnc->submittedMetaData, &defaultMetaDataSetup, |
697 | 0 | sizeof(AACENC_MetaData)); |
698 | 0 | metadataMode = hMetaDataEnc->finalizeMetaData; |
699 | 0 | hMetaDataEnc->finalizeMetaData = 0; |
700 | 0 | } |
701 | | |
702 | | /* Get last submitted data. */ |
703 | 0 | if ((err = LoadSubmittedMetadata( |
704 | 0 | &hMetaDataEnc->submittedMetaData, hMetaDataEnc->nChannels, |
705 | 0 | metadataMode, |
706 | 0 | &hMetaDataEnc->metaDataBuffer[metaDataDelayWriteIdx])) != |
707 | 0 | METADATA_OK) { |
708 | 0 | goto bail; |
709 | 0 | } |
710 | | |
711 | | /* Calculate compressor if necessary and updata meta data info */ |
712 | 0 | if ((hMetaDataEnc->metaDataBuffer[metaDataDelayWriteIdx].metadataMode == 1) || |
713 | 0 | (hMetaDataEnc->metaDataBuffer[metaDataDelayWriteIdx].metadataMode == 2)) { |
714 | 0 | if ((err = ProcessCompressor( |
715 | 0 | &hMetaDataEnc->metaDataBuffer[metaDataDelayWriteIdx], |
716 | 0 | hMetaDataEnc->hDrcComp, pAudioSamples, audioSamplesBufSize, |
717 | 0 | nAudioSamples)) != METADATA_OK) { |
718 | | /* Get last submitted data again. */ |
719 | 0 | LoadSubmittedMetadata( |
720 | 0 | &hMetaDataEnc->submittedMetaData, hMetaDataEnc->nChannels, |
721 | 0 | metadataMode, &hMetaDataEnc->metaDataBuffer[metaDataDelayWriteIdx]); |
722 | 0 | } |
723 | 0 | } |
724 | | |
725 | | /* Fill up delay line with initial meta data info.*/ |
726 | 0 | if ((hMetaDataEnc->initializeMetaData != 0) && |
727 | 0 | (hMetaDataEnc->metadataMode != 0)) { |
728 | 0 | int i; |
729 | 0 | for (i = 0; |
730 | 0 | i < (int)(sizeof(hMetaDataEnc->metaDataBuffer) / sizeof(AAC_METADATA)); |
731 | 0 | i++) { |
732 | 0 | if (i != metaDataDelayWriteIdx) { |
733 | 0 | FDKmemcpy(&hMetaDataEnc->metaDataBuffer[i], |
734 | 0 | &hMetaDataEnc->metaDataBuffer[metaDataDelayWriteIdx], |
735 | 0 | sizeof(hMetaDataEnc->metaDataBuffer[metaDataDelayWriteIdx])); |
736 | 0 | } |
737 | 0 | } |
738 | 0 | hMetaDataEnc->initializeMetaData = 0; |
739 | 0 | } |
740 | | |
741 | | /* Convert Meta Data side info to bitstream data. */ |
742 | 0 | FDK_ASSERT(metaDataDelayReadIdx < MAX_DELAY_FRAMES); |
743 | 0 | if ((err = WriteMetadataPayload( |
744 | 0 | hMetaDataEnc, |
745 | 0 | &hMetaDataEnc->metaDataBuffer[metaDataDelayReadIdx])) != |
746 | 0 | METADATA_OK) { |
747 | 0 | goto bail; |
748 | 0 | } |
749 | | |
750 | | /* Assign meta data to output */ |
751 | 0 | *ppMetaDataExtPayload = hMetaDataEnc->exPayload; |
752 | 0 | *nMetaDataExtensions = hMetaDataEnc->nExtensions; |
753 | 0 | *matrix_mixdown_idx = hMetaDataEnc->matrix_mixdown_idx; |
754 | |
|
755 | 0 | bail: |
756 | | /* Compensate audio delay, reset err status. */ |
757 | 0 | err = CompensateAudioDelay(hMetaDataEnc, pAudioSamples, audioSamplesBufSize, |
758 | 0 | nAudioSamples / hMetaDataEnc->nChannels); |
759 | |
|
760 | 0 | return err; |
761 | 0 | } |
762 | | |
763 | | static FDK_METADATA_ERROR CompensateAudioDelay( |
764 | | HANDLE_FDK_METADATA_ENCODER hMetaDataEnc, INT_PCM* const pAudioSamples, |
765 | 0 | const UINT audioSamplesBufSize, const INT nAudioSamples) { |
766 | 0 | FDK_METADATA_ERROR err = METADATA_OK; |
767 | |
|
768 | 0 | if (hMetaDataEnc->nAudioDataDelay) { |
769 | 0 | C_ALLOC_SCRATCH_START(scratch_audioDelayBuffer, INT_PCM, 1024); |
770 | |
|
771 | 0 | for (int c = 0; c < hMetaDataEnc->nChannels; c++) { |
772 | 0 | int M = 1024; |
773 | 0 | INT_PCM* pAudioSamples2 = pAudioSamples + c * audioSamplesBufSize; |
774 | 0 | int delayIdx = hMetaDataEnc->nAudioDataDelay; |
775 | |
|
776 | 0 | do { |
777 | 0 | M = fMin(M, delayIdx); |
778 | 0 | delayIdx -= M; |
779 | |
|
780 | 0 | FDKmemcpy(&scratch_audioDelayBuffer[0], |
781 | 0 | &pAudioSamples2[(nAudioSamples - M)], sizeof(INT_PCM) * M); |
782 | 0 | FDKmemmove(&pAudioSamples2[M], &pAudioSamples2[0], |
783 | 0 | sizeof(INT_PCM) * (nAudioSamples - M)); |
784 | 0 | FDKmemcpy( |
785 | 0 | &pAudioSamples2[0], |
786 | 0 | &hMetaDataEnc->pAudioDelayBuffer[delayIdx + |
787 | 0 | c * hMetaDataEnc->nAudioDataDelay], |
788 | 0 | sizeof(INT_PCM) * M); |
789 | 0 | FDKmemcpy( |
790 | 0 | &hMetaDataEnc->pAudioDelayBuffer[delayIdx + |
791 | 0 | c * hMetaDataEnc->nAudioDataDelay], |
792 | 0 | &scratch_audioDelayBuffer[0], sizeof(INT_PCM) * M); |
793 | |
|
794 | 0 | } while (delayIdx > 0); |
795 | 0 | } |
796 | |
|
797 | 0 | C_ALLOC_SCRATCH_END(scratch_audioDelayBuffer, INT_PCM, 1024); |
798 | 0 | } |
799 | |
|
800 | 0 | return err; |
801 | 0 | } |
802 | | |
803 | | /*----------------------------------------------------------------------------- |
804 | | |
805 | | functionname: WriteMetadataPayload |
806 | | description: fills anc data and extension payload |
807 | | returns: Error status |
808 | | |
809 | | ------------------------------------------------------------------------------*/ |
810 | | static FDK_METADATA_ERROR WriteMetadataPayload( |
811 | | const HANDLE_FDK_METADATA_ENCODER hMetaData, |
812 | 0 | const AAC_METADATA* const pMetadata) { |
813 | 0 | FDK_METADATA_ERROR err = METADATA_OK; |
814 | |
|
815 | 0 | if ((hMetaData == NULL) || (pMetadata == NULL)) { |
816 | 0 | err = METADATA_INVALID_HANDLE; |
817 | 0 | goto bail; |
818 | 0 | } |
819 | | |
820 | 0 | hMetaData->nExtensions = 0; |
821 | 0 | hMetaData->matrix_mixdown_idx = -1; |
822 | |
|
823 | 0 | if (pMetadata->metadataMode != 0) { |
824 | | /* AAC-DRC */ |
825 | 0 | if ((pMetadata->metadataMode == 1) || (pMetadata->metadataMode == 2)) { |
826 | 0 | hMetaData->exPayload[hMetaData->nExtensions].pData = |
827 | 0 | hMetaData->drcInfoPayload; |
828 | 0 | hMetaData->exPayload[hMetaData->nExtensions].dataType = EXT_DYNAMIC_RANGE; |
829 | 0 | hMetaData->exPayload[hMetaData->nExtensions].associatedChElement = -1; |
830 | |
|
831 | 0 | hMetaData->exPayload[hMetaData->nExtensions].dataSize = |
832 | 0 | WriteDynamicRangeInfoPayload( |
833 | 0 | pMetadata, hMetaData->exPayload[hMetaData->nExtensions].pData); |
834 | |
|
835 | 0 | hMetaData->nExtensions++; |
836 | 0 | } /* pMetadata->metadataMode==1 || pMetadata->metadataMode==2 */ |
837 | | |
838 | | /* Matrix Mixdown Coefficient in PCE */ |
839 | 0 | if (pMetadata->WritePCEMixDwnIdx) { |
840 | 0 | hMetaData->matrix_mixdown_idx = |
841 | 0 | surmix2matrix_mixdown_idx[pMetadata->surroundMixLevel]; |
842 | 0 | } |
843 | | |
844 | | /* ETSI TS 101 154 (DVB) - MPEG4 ancillary_data() */ |
845 | 0 | if ((pMetadata->metadataMode == 2) || |
846 | 0 | (pMetadata->metadataMode == 3)) /* MP4_METADATA_MPEG_ETSI */ |
847 | 0 | { |
848 | 0 | hMetaData->exPayload[hMetaData->nExtensions].pData = |
849 | 0 | hMetaData->drcDsePayload; |
850 | 0 | hMetaData->exPayload[hMetaData->nExtensions].dataType = EXT_DATA_ELEMENT; |
851 | 0 | hMetaData->exPayload[hMetaData->nExtensions].associatedChElement = -1; |
852 | |
|
853 | 0 | hMetaData->exPayload[hMetaData->nExtensions].dataSize = |
854 | 0 | WriteEtsiAncillaryDataPayload( |
855 | 0 | pMetadata, hMetaData->exPayload[hMetaData->nExtensions].pData); |
856 | |
|
857 | 0 | hMetaData->nExtensions++; |
858 | 0 | } /* metadataMode==2 || metadataMode==3 */ |
859 | |
|
860 | 0 | } /* metadataMode != 0 */ |
861 | |
|
862 | 0 | bail: |
863 | 0 | return err; |
864 | 0 | } |
865 | | |
866 | | static INT WriteDynamicRangeInfoPayload(const AAC_METADATA* const pMetadata, |
867 | 0 | UCHAR* const pExtensionPayload) { |
868 | 0 | const INT pce_tag_present = 0; /* yet fixed setting! */ |
869 | 0 | const INT prog_ref_lev_res_bits = 0; |
870 | 0 | INT i, drc_num_bands = 1; |
871 | |
|
872 | 0 | FDK_BITSTREAM bsWriter; |
873 | 0 | FDKinitBitStream(&bsWriter, pExtensionPayload, 16, 0, BS_WRITER); |
874 | | |
875 | | /* dynamic_range_info() */ |
876 | 0 | FDKwriteBits(&bsWriter, pce_tag_present, 1); /* pce_tag_present */ |
877 | 0 | if (pce_tag_present) { |
878 | 0 | FDKwriteBits(&bsWriter, 0x0, 4); /* pce_instance_tag */ |
879 | 0 | FDKwriteBits(&bsWriter, 0x0, 4); /* drc_tag_reserved_bits */ |
880 | 0 | } |
881 | | |
882 | | /* Exclude channels */ |
883 | 0 | FDKwriteBits(&bsWriter, (pMetadata->mpegDrc.excluded_chns_present) ? 1 : 0, |
884 | 0 | 1); /* excluded_chns_present*/ |
885 | | |
886 | | /* Multiband DRC */ |
887 | 0 | FDKwriteBits(&bsWriter, (pMetadata->mpegDrc.drc_bands_present) ? 1 : 0, |
888 | 0 | 1); /* drc_bands_present */ |
889 | 0 | if (pMetadata->mpegDrc.drc_bands_present) { |
890 | 0 | FDKwriteBits(&bsWriter, pMetadata->mpegDrc.drc_band_incr, |
891 | 0 | 4); /* drc_band_incr */ |
892 | 0 | FDKwriteBits(&bsWriter, pMetadata->mpegDrc.drc_interpolation_scheme, |
893 | 0 | 4); /* drc_interpolation_scheme */ |
894 | 0 | drc_num_bands += pMetadata->mpegDrc.drc_band_incr; |
895 | 0 | for (i = 0; i < drc_num_bands; i++) { |
896 | 0 | FDKwriteBits(&bsWriter, pMetadata->mpegDrc.drc_band_top[i], |
897 | 0 | 8); /* drc_band_top */ |
898 | 0 | } |
899 | 0 | } |
900 | | |
901 | | /* Program Reference Level */ |
902 | 0 | FDKwriteBits(&bsWriter, pMetadata->mpegDrc.prog_ref_level_present, |
903 | 0 | 1); /* prog_ref_level_present */ |
904 | 0 | if (pMetadata->mpegDrc.prog_ref_level_present) { |
905 | 0 | FDKwriteBits(&bsWriter, pMetadata->mpegDrc.prog_ref_level, |
906 | 0 | 7); /* prog_ref_level */ |
907 | 0 | FDKwriteBits(&bsWriter, prog_ref_lev_res_bits, |
908 | 0 | 1); /* prog_ref_level_reserved_bits */ |
909 | 0 | } |
910 | | |
911 | | /* DRC Values */ |
912 | 0 | for (i = 0; i < drc_num_bands; i++) { |
913 | 0 | FDKwriteBits(&bsWriter, (pMetadata->mpegDrc.dyn_rng_sgn[i]) ? 1 : 0, |
914 | 0 | 1); /* dyn_rng_sgn[ */ |
915 | 0 | FDKwriteBits(&bsWriter, pMetadata->mpegDrc.dyn_rng_ctl[i], |
916 | 0 | 7); /* dyn_rng_ctl */ |
917 | 0 | } |
918 | | |
919 | | /* return number of valid bits in extension payload. */ |
920 | 0 | return FDKgetValidBits(&bsWriter); |
921 | 0 | } |
922 | | |
923 | | static INT WriteEtsiAncillaryDataPayload(const AAC_METADATA* const pMetadata, |
924 | 0 | UCHAR* const pExtensionPayload) { |
925 | 0 | FDK_BITSTREAM bsWriter; |
926 | 0 | FDKinitBitStream(&bsWriter, pExtensionPayload, 16, 0, BS_WRITER); |
927 | | |
928 | | /* ancillary_data_sync */ |
929 | 0 | FDKwriteBits(&bsWriter, 0xBC, 8); |
930 | | |
931 | | /* bs_info */ |
932 | 0 | FDKwriteBits(&bsWriter, 0x3, 2); /* mpeg_audio_type */ |
933 | 0 | FDKwriteBits(&bsWriter, pMetadata->dolbySurroundMode, |
934 | 0 | 2); /* dolby_surround_mode */ |
935 | 0 | FDKwriteBits(&bsWriter, pMetadata->drcPresentationMode, |
936 | 0 | 2); /* DRC presentation mode */ |
937 | 0 | FDKwriteBits(&bsWriter, 0x0, 1); /* stereo_downmix_mode */ |
938 | 0 | FDKwriteBits(&bsWriter, 0x0, 1); /* reserved */ |
939 | | |
940 | | /* ancillary_data_status */ |
941 | 0 | FDKwriteBits(&bsWriter, 0, 3); /* 3 bit Reserved, set to "0" */ |
942 | 0 | FDKwriteBits(&bsWriter, (pMetadata->DmxLvl_On) ? 1 : 0, |
943 | 0 | 1); /* downmixing_levels_MPEG4_status */ |
944 | 0 | FDKwriteBits(&bsWriter, pMetadata->etsiAncData.extAncDataStatus, |
945 | 0 | 1); /* ext_anc_data_status */ |
946 | 0 | FDKwriteBits(&bsWriter, (pMetadata->etsiAncData.compression_on) ? 1 : 0, |
947 | 0 | 1); /* audio_coding_mode_and_compression status */ |
948 | 0 | FDKwriteBits(&bsWriter, |
949 | 0 | (pMetadata->etsiAncData.timecode_coarse_status) ? 1 : 0, |
950 | 0 | 1); /* coarse_grain_timecode_status */ |
951 | 0 | FDKwriteBits(&bsWriter, (pMetadata->etsiAncData.timecode_fine_status) ? 1 : 0, |
952 | 0 | 1); /* fine_grain_timecode_status */ |
953 | | |
954 | | /* downmixing_levels_MPEG4_status */ |
955 | 0 | if (pMetadata->DmxLvl_On) { |
956 | 0 | FDKwriteBits( |
957 | 0 | &bsWriter, |
958 | 0 | encodeDmxLvls(pMetadata->centerMixLevel, pMetadata->surroundMixLevel), |
959 | 0 | 8); |
960 | 0 | } |
961 | | |
962 | | /* audio_coding_mode_and_compression_status */ |
963 | 0 | if (pMetadata->etsiAncData.compression_on) { |
964 | 0 | FDKwriteBits(&bsWriter, 0x01, 8); /* audio coding mode */ |
965 | 0 | FDKwriteBits(&bsWriter, pMetadata->etsiAncData.compression_value, |
966 | 0 | 8); /* compression value */ |
967 | 0 | } |
968 | | |
969 | | /* grain-timecode coarse/fine */ |
970 | 0 | if (pMetadata->etsiAncData.timecode_coarse_status) { |
971 | 0 | FDKwriteBits(&bsWriter, 0x0, 16); /* not yet supported */ |
972 | 0 | } |
973 | |
|
974 | 0 | if (pMetadata->etsiAncData.timecode_fine_status) { |
975 | 0 | FDKwriteBits(&bsWriter, 0x0, 16); /* not yet supported */ |
976 | 0 | } |
977 | | |
978 | | /* extended ancillary data structure */ |
979 | 0 | if (pMetadata->etsiAncData.extAncDataStatus) { |
980 | | /* ext_ancillary_data_status */ |
981 | 0 | FDKwriteBits(&bsWriter, 0, 1); /* Reserved, set to "0" */ |
982 | 0 | FDKwriteBits(&bsWriter, |
983 | 0 | pMetadata->etsiAncData.extAncData.ext_downmix_lvl_status, |
984 | 0 | 1); /* ext_downmixing_levels_status */ |
985 | 0 | FDKwriteBits(&bsWriter, |
986 | 0 | pMetadata->etsiAncData.extAncData.ext_downmix_gain_status, |
987 | 0 | 1); /* ext_downmixing_global_gains_status */ |
988 | 0 | FDKwriteBits(&bsWriter, |
989 | 0 | pMetadata->etsiAncData.extAncData.ext_lfe_downmix_status, |
990 | 0 | 1); /* ext_downmixing_lfe_level_status" */ |
991 | 0 | FDKwriteBits(&bsWriter, 0, 4); /* Reserved, set to "0" */ |
992 | | |
993 | | /* ext_downmixing_levels */ |
994 | 0 | if (pMetadata->etsiAncData.extAncData.ext_downmix_lvl_status) { |
995 | 0 | FDKwriteBits(&bsWriter, pMetadata->etsiAncData.extAncData.ext_dmix_a_idx, |
996 | 0 | 3); /* dmix_a_idx */ |
997 | 0 | FDKwriteBits(&bsWriter, pMetadata->etsiAncData.extAncData.ext_dmix_b_idx, |
998 | 0 | 3); /* dmix_b_idx */ |
999 | 0 | FDKwriteBits(&bsWriter, 0, 2); /* Reserved, set to "0" */ |
1000 | 0 | } |
1001 | | |
1002 | | /* ext_downmixing_gains */ |
1003 | 0 | if (pMetadata->etsiAncData.extAncData.ext_downmix_gain_status) { |
1004 | 0 | FDKwriteBits(&bsWriter, pMetadata->etsiAncData.extAncData.dmx_gain_5_sgn, |
1005 | 0 | 1); /* dmx_gain_5_sign */ |
1006 | 0 | FDKwriteBits(&bsWriter, pMetadata->etsiAncData.extAncData.dmx_gain_5_idx, |
1007 | 0 | 6); /* dmx_gain_5_idx */ |
1008 | 0 | FDKwriteBits(&bsWriter, 0, 1); /* Reserved, set to "0" */ |
1009 | 0 | FDKwriteBits(&bsWriter, pMetadata->etsiAncData.extAncData.dmx_gain_2_sgn, |
1010 | 0 | 1); /* dmx_gain_2_sign */ |
1011 | 0 | FDKwriteBits(&bsWriter, pMetadata->etsiAncData.extAncData.dmx_gain_2_idx, |
1012 | 0 | 6); /* dmx_gain_2_idx */ |
1013 | 0 | FDKwriteBits(&bsWriter, 0, 1); /* Reserved, set to "0" */ |
1014 | 0 | } |
1015 | |
|
1016 | 0 | if (pMetadata->etsiAncData.extAncData.ext_lfe_downmix_status) { |
1017 | 0 | FDKwriteBits(&bsWriter, |
1018 | 0 | pMetadata->etsiAncData.extAncData.ext_dmix_lfe_idx, |
1019 | 0 | 4); /* dmix_lfe_idx */ |
1020 | 0 | FDKwriteBits(&bsWriter, 0, 4); /* Reserved, set to "0" */ |
1021 | 0 | } |
1022 | 0 | } |
1023 | |
|
1024 | 0 | return FDKgetValidBits(&bsWriter); |
1025 | 0 | } |
1026 | | |
1027 | | static FDK_METADATA_ERROR LoadSubmittedMetadata( |
1028 | | const AACENC_MetaData* const hMetadata, const INT nChannels, |
1029 | 0 | const INT metadataMode, AAC_METADATA* const pAacMetaData) { |
1030 | 0 | FDK_METADATA_ERROR err = METADATA_OK; |
1031 | |
|
1032 | 0 | if (pAacMetaData == NULL) { |
1033 | 0 | err = METADATA_INVALID_HANDLE; |
1034 | 0 | } else { |
1035 | | /* init struct */ |
1036 | 0 | FDKmemclear(pAacMetaData, sizeof(AAC_METADATA)); |
1037 | |
|
1038 | 0 | if (hMetadata != NULL) { |
1039 | | /* convert data */ |
1040 | 0 | pAacMetaData->mpegDrc.drc_profile = hMetadata->drc_profile; |
1041 | 0 | pAacMetaData->etsiAncData.comp_profile = hMetadata->comp_profile; |
1042 | 0 | pAacMetaData->mpegDrc.drc_TargetRefLevel = hMetadata->drc_TargetRefLevel; |
1043 | 0 | pAacMetaData->etsiAncData.comp_TargetRefLevel = |
1044 | 0 | hMetadata->comp_TargetRefLevel; |
1045 | 0 | pAacMetaData->mpegDrc.prog_ref_level_present = |
1046 | 0 | hMetadata->prog_ref_level_present; |
1047 | 0 | pAacMetaData->mpegDrc.prog_ref_level = |
1048 | 0 | dialnorm2progreflvl(hMetadata->prog_ref_level); |
1049 | |
|
1050 | 0 | pAacMetaData->centerMixLevel = hMetadata->centerMixLevel; |
1051 | 0 | pAacMetaData->surroundMixLevel = hMetadata->surroundMixLevel; |
1052 | 0 | pAacMetaData->WritePCEMixDwnIdx = hMetadata->PCE_mixdown_idx_present; |
1053 | 0 | pAacMetaData->DmxLvl_On = hMetadata->ETSI_DmxLvl_present; |
1054 | |
|
1055 | 0 | pAacMetaData->etsiAncData.compression_on = |
1056 | 0 | (hMetadata->comp_profile == AACENC_METADATA_DRC_NOT_PRESENT ? 0 : 1); |
1057 | |
|
1058 | 0 | if (pAacMetaData->mpegDrc.drc_profile == |
1059 | 0 | AACENC_METADATA_DRC_NOT_PRESENT) { |
1060 | 0 | pAacMetaData->mpegDrc.drc_profile = |
1061 | 0 | AACENC_METADATA_DRC_NONE; /* MPEG DRC gains are |
1062 | | always present in BS |
1063 | | syntax */ |
1064 | | /* we should give a warning, but ErrorHandler does not support this */ |
1065 | 0 | } |
1066 | |
|
1067 | 0 | if (nChannels == 2) { |
1068 | 0 | pAacMetaData->dolbySurroundMode = |
1069 | 0 | hMetadata->dolbySurroundMode; /* dolby_surround_mode */ |
1070 | 0 | } else { |
1071 | 0 | pAacMetaData->dolbySurroundMode = 0; |
1072 | 0 | } |
1073 | |
|
1074 | 0 | pAacMetaData->drcPresentationMode = hMetadata->drcPresentationMode; |
1075 | | /* override external values if DVB DRC presentation mode is given */ |
1076 | 0 | if (pAacMetaData->drcPresentationMode == 1) { |
1077 | 0 | pAacMetaData->mpegDrc.drc_TargetRefLevel = |
1078 | 0 | fMax(-(31 << 16), pAacMetaData->mpegDrc.drc_TargetRefLevel); |
1079 | 0 | pAacMetaData->etsiAncData.comp_TargetRefLevel = fMax( |
1080 | 0 | -(20 << 16), |
1081 | 0 | pAacMetaData->etsiAncData.comp_TargetRefLevel); /* implies -23dB */ |
1082 | 0 | } |
1083 | 0 | if (pAacMetaData->drcPresentationMode == 2) { |
1084 | 0 | pAacMetaData->mpegDrc.drc_TargetRefLevel = |
1085 | 0 | fMax(-(23 << 16), pAacMetaData->mpegDrc.drc_TargetRefLevel); |
1086 | 0 | pAacMetaData->etsiAncData.comp_TargetRefLevel = |
1087 | 0 | fMax(-(23 << 16), pAacMetaData->etsiAncData.comp_TargetRefLevel); |
1088 | 0 | } |
1089 | 0 | if (pAacMetaData->etsiAncData.comp_profile == |
1090 | 0 | AACENC_METADATA_DRC_NOT_PRESENT) { |
1091 | | /* DVB defines to revert to Light DRC if heavy is not present */ |
1092 | 0 | if (pAacMetaData->drcPresentationMode != 0) { |
1093 | | /* we exclude the "not indicated" mode as this requires the user to |
1094 | | * define desired levels anyway */ |
1095 | 0 | pAacMetaData->mpegDrc.drc_TargetRefLevel = |
1096 | 0 | fMax(pAacMetaData->etsiAncData.comp_TargetRefLevel, |
1097 | 0 | pAacMetaData->mpegDrc.drc_TargetRefLevel); |
1098 | 0 | } |
1099 | 0 | } |
1100 | |
|
1101 | 0 | pAacMetaData->etsiAncData.timecode_coarse_status = |
1102 | 0 | 0; /* not yet supported - attention: Update |
1103 | | GetEstMetadataBytesPerFrame() if enable this! */ |
1104 | 0 | pAacMetaData->etsiAncData.timecode_fine_status = |
1105 | 0 | 0; /* not yet supported - attention: Update |
1106 | | GetEstMetadataBytesPerFrame() if enable this! */ |
1107 | | |
1108 | | /* extended ancillary data */ |
1109 | 0 | pAacMetaData->etsiAncData.extAncDataStatus = |
1110 | 0 | ((hMetadata->ExtMetaData.extAncDataEnable == 1) ? 1 : 0); |
1111 | |
|
1112 | 0 | if (pAacMetaData->etsiAncData.extAncDataStatus) { |
1113 | 0 | pAacMetaData->etsiAncData.extAncData.ext_downmix_lvl_status = |
1114 | 0 | (hMetadata->ExtMetaData.extDownmixLevelEnable ? 1 : 0); |
1115 | 0 | pAacMetaData->etsiAncData.extAncData.ext_downmix_gain_status = |
1116 | 0 | (hMetadata->ExtMetaData.dmxGainEnable ? 1 : 0); |
1117 | 0 | pAacMetaData->etsiAncData.extAncData.ext_lfe_downmix_status = |
1118 | 0 | (hMetadata->ExtMetaData.lfeDmxEnable ? 1 : 0); |
1119 | |
|
1120 | 0 | pAacMetaData->etsiAncData.extAncData.ext_dmix_a_idx = |
1121 | 0 | hMetadata->ExtMetaData.extDownmixLevel_A; |
1122 | 0 | pAacMetaData->etsiAncData.extAncData.ext_dmix_b_idx = |
1123 | 0 | hMetadata->ExtMetaData.extDownmixLevel_B; |
1124 | |
|
1125 | 0 | if (pAacMetaData->etsiAncData.extAncData.ext_downmix_gain_status) { |
1126 | 0 | encodeDynrng(hMetadata->ExtMetaData.dmxGain5, |
1127 | 0 | &(pAacMetaData->etsiAncData.extAncData.dmx_gain_5_idx), |
1128 | 0 | &(pAacMetaData->etsiAncData.extAncData.dmx_gain_5_sgn)); |
1129 | 0 | encodeDynrng(hMetadata->ExtMetaData.dmxGain2, |
1130 | 0 | &(pAacMetaData->etsiAncData.extAncData.dmx_gain_2_idx), |
1131 | 0 | &(pAacMetaData->etsiAncData.extAncData.dmx_gain_2_sgn)); |
1132 | 0 | } else { |
1133 | 0 | encodeDynrng(1 << 16, |
1134 | 0 | &(pAacMetaData->etsiAncData.extAncData.dmx_gain_5_idx), |
1135 | 0 | &(pAacMetaData->etsiAncData.extAncData.dmx_gain_5_sgn)); |
1136 | 0 | encodeDynrng(1 << 16, |
1137 | 0 | &(pAacMetaData->etsiAncData.extAncData.dmx_gain_2_idx), |
1138 | 0 | &(pAacMetaData->etsiAncData.extAncData.dmx_gain_2_sgn)); |
1139 | 0 | } |
1140 | |
|
1141 | 0 | if (pAacMetaData->etsiAncData.extAncData.ext_lfe_downmix_status) { |
1142 | 0 | pAacMetaData->etsiAncData.extAncData.ext_dmix_lfe_idx = |
1143 | 0 | hMetadata->ExtMetaData.lfeDmxLevel; |
1144 | 0 | } else { |
1145 | 0 | pAacMetaData->etsiAncData.extAncData.ext_dmix_lfe_idx = |
1146 | 0 | 15; /* -inf dB */ |
1147 | 0 | } |
1148 | 0 | } else { |
1149 | 0 | pAacMetaData->etsiAncData.extAncData.ext_downmix_lvl_status = 0; |
1150 | 0 | pAacMetaData->etsiAncData.extAncData.ext_downmix_gain_status = 0; |
1151 | 0 | pAacMetaData->etsiAncData.extAncData.ext_lfe_downmix_status = 0; |
1152 | |
|
1153 | 0 | pAacMetaData->etsiAncData.extAncData.ext_dmix_a_idx = 7; /* -inf dB */ |
1154 | 0 | pAacMetaData->etsiAncData.extAncData.ext_dmix_b_idx = 7; /* -inf dB */ |
1155 | |
|
1156 | 0 | encodeDynrng(1 << 16, |
1157 | 0 | &(pAacMetaData->etsiAncData.extAncData.dmx_gain_5_idx), |
1158 | 0 | &(pAacMetaData->etsiAncData.extAncData.dmx_gain_5_sgn)); |
1159 | 0 | encodeDynrng(1 << 16, |
1160 | 0 | &(pAacMetaData->etsiAncData.extAncData.dmx_gain_2_idx), |
1161 | 0 | &(pAacMetaData->etsiAncData.extAncData.dmx_gain_2_sgn)); |
1162 | |
|
1163 | 0 | pAacMetaData->etsiAncData.extAncData.ext_dmix_lfe_idx = |
1164 | 0 | 15; /* -inf dB */ |
1165 | 0 | } |
1166 | |
|
1167 | 0 | pAacMetaData->metadataMode = metadataMode; |
1168 | 0 | } else { |
1169 | 0 | pAacMetaData->metadataMode = 0; /* there is no configuration available */ |
1170 | 0 | } |
1171 | 0 | } |
1172 | |
|
1173 | 0 | return err; |
1174 | 0 | } |
1175 | | |
1176 | 0 | INT FDK_MetadataEnc_GetDelay(HANDLE_FDK_METADATA_ENCODER hMetadataEnc) { |
1177 | 0 | INT delay = 0; |
1178 | |
|
1179 | 0 | if (hMetadataEnc != NULL) { |
1180 | 0 | delay = hMetadataEnc->nAudioDataDelay; |
1181 | 0 | } |
1182 | |
|
1183 | 0 | return delay; |
1184 | 0 | } |