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