Coverage Report

Created: 2025-07-01 06:21

/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
}