Coverage Report

Created: 2026-02-14 06:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/fdk-aac/libAACenc/src/metadata_main.cpp
Line
Count
Source
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
      if (channelOrder == CH_ORDER_WG4) {
495
0
        FDK_chMapDescr_init(&mapDescrPrev, FDK_mapInfoTabWg4,
496
0
                            FDK_mapInfoTabLenWg4, 0);
497
0
        FDK_chMapDescr_init(&mapDescr, FDK_mapInfoTabWg4,
498
0
                            FDK_mapInfoTabLenWg4, 0);
499
0
      } else {
500
0
        FDK_chMapDescr_init(&mapDescrPrev, NULL, 0,
501
0
                            (channelOrder == CH_ORDER_MPEG) ? 1 : 0);
502
0
        FDK_chMapDescr_init(&mapDescr, NULL, 0,
503
0
                            (channelOrder == CH_ORDER_MPEG) ? 1 : 0);
504
0
      }
505
506
0
      switch (channelMode) {
507
0
        case MODE_1:
508
0
          if ((INT)nChannels != 2) {
509
            /* preserve center channel */
510
0
            src[0] = FDK_chMapDescr_getMapValue(&mapDescrPrev, 0,
511
0
                                                hMetaData->channelMode);
512
0
            dst[0] = FDK_chMapDescr_getMapValue(&mapDescr, 0, channelMode);
513
0
          }
514
0
          break;
515
0
        case MODE_2:
516
0
        case MODE_1_2:
517
0
        case MODE_1_2_1:
518
0
        case MODE_1_2_2:
519
0
        case MODE_1_2_2_1:
520
0
          if (hMetaData->nChannels >= 2) {
521
            /* preserve left/right channel */
522
0
            src[0] = FDK_chMapDescr_getMapValue(
523
0
                &mapDescrPrev, ((hMetaData->channelMode == 2) ? 0 : 1),
524
0
                hMetaData->channelMode);
525
0
            src[1] = FDK_chMapDescr_getMapValue(
526
0
                &mapDescrPrev, ((hMetaData->channelMode == 2) ? 1 : 2),
527
0
                hMetaData->channelMode);
528
0
            dst[0] = FDK_chMapDescr_getMapValue(
529
0
                &mapDescr, ((channelMode == 2) ? 0 : 1), channelMode);
530
0
            dst[1] = FDK_chMapDescr_getMapValue(
531
0
                &mapDescr, ((channelMode == 2) ? 1 : 2), channelMode);
532
0
          }
533
0
          break;
534
0
        default:;
535
0
      }
536
0
      C_ALLOC_SCRATCH_START(scratch_audioDelayBuffer, INT_PCM, (8));
537
0
      FDKmemclear(scratch_audioDelayBuffer, (8) * sizeof(INT_PCM));
538
539
0
      i = (hMetaData->nChannels > (INT)nChannels)
540
0
              ? 0
541
0
              : hMetaData->nAudioDataDelay - 1;
542
0
      do {
543
0
        for (c = 0; c < 2; c++) {
544
0
          if (src[c] != -1 && dst[c] != -1) {
545
0
            scratch_audioDelayBuffer[dst[c]] =
546
0
                hMetaData->pAudioDelayBuffer[i * hMetaData->nChannels + src[c]];
547
0
          }
548
0
        }
549
0
        FDKmemcpy(&hMetaData->pAudioDelayBuffer[i * nChannels],
550
0
                  scratch_audioDelayBuffer, nChannels * sizeof(INT_PCM));
551
0
        i += (hMetaData->nChannels > (INT)nChannels) ? 1 : -1;
552
0
      } while ((i < hMetaData->nAudioDataDelay) && (i >= 0));
553
554
0
      C_ALLOC_SCRATCH_END(scratch_audioDelayBuffer, INT_PCM, (8));
555
0
    }
556
0
    FDKmemclear(hMetaData->metaDataBuffer, sizeof(hMetaData->metaDataBuffer));
557
0
    hMetaData->metaDataDelayIdx = 0;
558
0
    hMetaData->initializeMetaData =
559
0
        1; /* fill up delay line with first meta data info */
560
0
  } else {
561
    /* Enable meta data. */
562
0
    if ((hMetaData->metadataMode == 0) && (metadataMode != 0)) {
563
      /* disable meta data in all delay lines */
564
0
      for (i = 0;
565
0
           i < (int)(sizeof(hMetaData->metaDataBuffer) / sizeof(AAC_METADATA));
566
0
           i++) {
567
0
        LoadSubmittedMetadata(&hMetaData->submittedMetaData, nChannels, 0,
568
0
                              &hMetaData->metaDataBuffer[i]);
569
0
      }
570
0
    }
571
572
    /* Disable meta data.*/
573
0
    if ((hMetaData->metadataMode != 0) && (metadataMode == 0)) {
574
0
      hMetaData->finalizeMetaData = hMetaData->metadataMode;
575
0
    }
576
0
  }
577
578
  /* Initialize delay. */
579
0
  hMetaData->nAudioDataDelay = -delay;
580
0
  hMetaData->nMetaDataDelay = nFrames;
581
0
  hMetaData->nChannels = nChannels;
582
0
  hMetaData->channelMode = channelMode;
583
0
  hMetaData->metadataMode = metadataMode;
584
585
  /* Initialize compressor. */
586
0
  if ((metadataMode == 1) || (metadataMode == 2)) {
587
0
    if (FDK_DRC_Generator_Initialize(hMetaData->hDrcComp, DRC_NONE, DRC_NONE,
588
0
                                     frameLength, sampleRate, channelMode,
589
0
                                     channelOrder, 1) != 0) {
590
0
      err = METADATA_INIT_ERROR;
591
0
    }
592
0
  }
593
0
bail:
594
0
  return err;
595
0
}
596
597
static FDK_METADATA_ERROR ProcessCompressor(AAC_METADATA* pMetadata,
598
                                            HDRC_COMP hDrcComp,
599
                                            const INT_PCM* const pSamples,
600
                                            const UINT samplesBufSize,
601
0
                                            const INT nSamples) {
602
0
  FDK_METADATA_ERROR err = METADATA_OK;
603
604
0
  INT dynrng, compr;
605
0
  INT dmxGain5, dmxGain2;
606
0
  DRC_PROFILE profileDrc;
607
0
  DRC_PROFILE profileComp;
608
609
0
  if ((pMetadata == NULL) || (hDrcComp == NULL)) {
610
0
    err = METADATA_INVALID_HANDLE;
611
0
    return err;
612
0
  }
613
614
0
  profileDrc = convertProfile(pMetadata->mpegDrc.drc_profile);
615
0
  profileComp = convertProfile(pMetadata->etsiAncData.comp_profile);
616
617
  /* first, check if profile is same as last frame
618
   * otherwise, update setup */
619
0
  if ((profileDrc != FDK_DRC_Generator_getDrcProfile(hDrcComp)) ||
620
0
      (profileComp != FDK_DRC_Generator_getCompProfile(hDrcComp))) {
621
0
    FDK_DRC_Generator_setDrcProfile(hDrcComp, profileDrc, profileComp);
622
0
  }
623
624
  /* Sanity check */
625
0
  if (profileComp == DRC_NONE) {
626
0
    pMetadata->etsiAncData.compression_value = 0x80; /* to ensure no external
627
                                                        values will be written
628
                                                        if not configured */
629
0
  }
630
631
  /* in case of embedding external values, copy this now (limiter may overwrite
632
   * them) */
633
0
  dynrng = decodeDynrng(pMetadata->mpegDrc.dyn_rng_ctl[0],
634
0
                        pMetadata->mpegDrc.dyn_rng_sgn[0]);
635
0
  compr = decodeCompr(pMetadata->etsiAncData.compression_value);
636
637
0
  dmxGain5 = decodeDynrng(pMetadata->etsiAncData.extAncData.dmx_gain_5_idx,
638
0
                          pMetadata->etsiAncData.extAncData.dmx_gain_5_sgn);
639
0
  dmxGain2 = decodeDynrng(pMetadata->etsiAncData.extAncData.dmx_gain_2_idx,
640
0
                          pMetadata->etsiAncData.extAncData.dmx_gain_2_sgn);
641
642
  /* Call compressor */
643
0
  if (FDK_DRC_Generator_Calc(
644
0
          hDrcComp, pSamples, samplesBufSize,
645
0
          progreflvl2dialnorm(pMetadata->mpegDrc.prog_ref_level),
646
0
          pMetadata->mpegDrc.drc_TargetRefLevel,
647
0
          pMetadata->etsiAncData.comp_TargetRefLevel,
648
0
          dmxTable[pMetadata->centerMixLevel],
649
0
          dmxTable[pMetadata->surroundMixLevel],
650
0
          dmxTable[pMetadata->etsiAncData.extAncData.ext_dmix_a_idx],
651
0
          dmxTable[pMetadata->etsiAncData.extAncData.ext_dmix_b_idx],
652
0
          pMetadata->etsiAncData.extAncData.ext_lfe_downmix_status
653
0
              ? dmxLfeTable[pMetadata->etsiAncData.extAncData.ext_dmix_lfe_idx]
654
0
              : (FIXP_DBL)0,
655
0
          dmxGain5, dmxGain2, &dynrng, &compr) != 0) {
656
0
    err = METADATA_ENCODE_ERROR;
657
0
    goto bail;
658
0
  }
659
660
  /* Write DRC values */
661
0
  pMetadata->mpegDrc.drc_band_incr = 0;
662
0
  encodeDynrng(dynrng, pMetadata->mpegDrc.dyn_rng_ctl,
663
0
               pMetadata->mpegDrc.dyn_rng_sgn);
664
0
  pMetadata->etsiAncData.compression_value = encodeCompr(compr);
665
666
0
bail:
667
0
  return err;
668
0
}
669
670
FDK_METADATA_ERROR FDK_MetadataEnc_Process(
671
    HANDLE_FDK_METADATA_ENCODER hMetaDataEnc, INT_PCM* const pAudioSamples,
672
    const UINT audioSamplesBufSize, const INT nAudioSamples,
673
    const AACENC_MetaData* const pMetadata,
674
    AACENC_EXT_PAYLOAD** ppMetaDataExtPayload, UINT* nMetaDataExtensions,
675
0
    INT* matrix_mixdown_idx) {
676
0
  FDK_METADATA_ERROR err = METADATA_OK;
677
0
  int metaDataDelayWriteIdx, metaDataDelayReadIdx, metadataMode;
678
679
  /* Where to write new meta data info */
680
0
  metaDataDelayWriteIdx = hMetaDataEnc->metaDataDelayIdx;
681
682
  /* How to write the data */
683
0
  metadataMode = hMetaDataEnc->metadataMode;
684
685
  /* Compensate meta data delay. */
686
0
  hMetaDataEnc->metaDataDelayIdx++;
687
0
  if (hMetaDataEnc->metaDataDelayIdx > hMetaDataEnc->nMetaDataDelay)
688
0
    hMetaDataEnc->metaDataDelayIdx = 0;
689
690
  /* Where to read pending meta data info from. */
691
0
  metaDataDelayReadIdx = hMetaDataEnc->metaDataDelayIdx;
692
693
  /* Submit new data if available. */
694
0
  if (pMetadata != NULL) {
695
0
    FDKmemcpy(&hMetaDataEnc->submittedMetaData, pMetadata,
696
0
              sizeof(AACENC_MetaData));
697
0
  }
698
699
  /* Write one additional frame with default configuration of meta data. Ensure
700
   * defined behaviour on decoder side. */
701
0
  if ((hMetaDataEnc->finalizeMetaData != 0) &&
702
0
      (hMetaDataEnc->metadataMode == 0)) {
703
0
    FDKmemcpy(&hMetaDataEnc->submittedMetaData, &defaultMetaDataSetup,
704
0
              sizeof(AACENC_MetaData));
705
0
    metadataMode = hMetaDataEnc->finalizeMetaData;
706
0
    hMetaDataEnc->finalizeMetaData = 0;
707
0
  }
708
709
  /* Get last submitted data. */
710
0
  if ((err = LoadSubmittedMetadata(
711
0
           &hMetaDataEnc->submittedMetaData, hMetaDataEnc->nChannels,
712
0
           metadataMode,
713
0
           &hMetaDataEnc->metaDataBuffer[metaDataDelayWriteIdx])) !=
714
0
      METADATA_OK) {
715
0
    goto bail;
716
0
  }
717
718
  /* Calculate compressor if necessary and updata meta data info */
719
0
  if ((hMetaDataEnc->metaDataBuffer[metaDataDelayWriteIdx].metadataMode == 1) ||
720
0
      (hMetaDataEnc->metaDataBuffer[metaDataDelayWriteIdx].metadataMode == 2)) {
721
0
    if ((err = ProcessCompressor(
722
0
             &hMetaDataEnc->metaDataBuffer[metaDataDelayWriteIdx],
723
0
             hMetaDataEnc->hDrcComp, pAudioSamples, audioSamplesBufSize,
724
0
             nAudioSamples)) != METADATA_OK) {
725
      /* Get last submitted data again. */
726
0
      LoadSubmittedMetadata(
727
0
          &hMetaDataEnc->submittedMetaData, hMetaDataEnc->nChannels,
728
0
          metadataMode, &hMetaDataEnc->metaDataBuffer[metaDataDelayWriteIdx]);
729
0
    }
730
0
  }
731
732
  /* Fill up delay line with initial meta data info.*/
733
0
  if ((hMetaDataEnc->initializeMetaData != 0) &&
734
0
      (hMetaDataEnc->metadataMode != 0)) {
735
0
    int i;
736
0
    for (i = 0;
737
0
         i < (int)(sizeof(hMetaDataEnc->metaDataBuffer) / sizeof(AAC_METADATA));
738
0
         i++) {
739
0
      if (i != metaDataDelayWriteIdx) {
740
0
        FDKmemcpy(&hMetaDataEnc->metaDataBuffer[i],
741
0
                  &hMetaDataEnc->metaDataBuffer[metaDataDelayWriteIdx],
742
0
                  sizeof(hMetaDataEnc->metaDataBuffer[metaDataDelayWriteIdx]));
743
0
      }
744
0
    }
745
0
    hMetaDataEnc->initializeMetaData = 0;
746
0
  }
747
748
  /* Convert Meta Data side info to bitstream data. */
749
0
  FDK_ASSERT(metaDataDelayReadIdx < MAX_DELAY_FRAMES);
750
0
  if ((err = WriteMetadataPayload(
751
0
           hMetaDataEnc,
752
0
           &hMetaDataEnc->metaDataBuffer[metaDataDelayReadIdx])) !=
753
0
      METADATA_OK) {
754
0
    goto bail;
755
0
  }
756
757
  /* Assign meta data to output */
758
0
  *ppMetaDataExtPayload = hMetaDataEnc->exPayload;
759
0
  *nMetaDataExtensions = hMetaDataEnc->nExtensions;
760
0
  *matrix_mixdown_idx = hMetaDataEnc->matrix_mixdown_idx;
761
762
0
bail:
763
  /* Compensate audio delay, reset err status. */
764
0
  err = CompensateAudioDelay(hMetaDataEnc, pAudioSamples, audioSamplesBufSize,
765
0
                             nAudioSamples / hMetaDataEnc->nChannels);
766
767
0
  return err;
768
0
}
769
770
static FDK_METADATA_ERROR CompensateAudioDelay(
771
    HANDLE_FDK_METADATA_ENCODER hMetaDataEnc, INT_PCM* const pAudioSamples,
772
0
    const UINT audioSamplesBufSize, const INT nAudioSamples) {
773
0
  FDK_METADATA_ERROR err = METADATA_OK;
774
775
0
  if (hMetaDataEnc->nAudioDataDelay) {
776
0
    C_ALLOC_SCRATCH_START(scratch_audioDelayBuffer, INT_PCM, 1024);
777
778
0
    for (int c = 0; c < hMetaDataEnc->nChannels; c++) {
779
0
      int M = 1024;
780
0
      INT_PCM* pAudioSamples2 = pAudioSamples + c * audioSamplesBufSize;
781
0
      int delayIdx = hMetaDataEnc->nAudioDataDelay;
782
783
0
      do {
784
0
        M = fMin(M, delayIdx);
785
0
        delayIdx -= M;
786
787
0
        FDKmemcpy(&scratch_audioDelayBuffer[0],
788
0
                  &pAudioSamples2[(nAudioSamples - M)], sizeof(INT_PCM) * M);
789
0
        FDKmemmove(&pAudioSamples2[M], &pAudioSamples2[0],
790
0
                   sizeof(INT_PCM) * (nAudioSamples - M));
791
0
        FDKmemcpy(
792
0
            &pAudioSamples2[0],
793
0
            &hMetaDataEnc->pAudioDelayBuffer[delayIdx +
794
0
                                             c * hMetaDataEnc->nAudioDataDelay],
795
0
            sizeof(INT_PCM) * M);
796
0
        FDKmemcpy(
797
0
            &hMetaDataEnc->pAudioDelayBuffer[delayIdx +
798
0
                                             c * hMetaDataEnc->nAudioDataDelay],
799
0
            &scratch_audioDelayBuffer[0], sizeof(INT_PCM) * M);
800
801
0
      } while (delayIdx > 0);
802
0
    }
803
804
0
    C_ALLOC_SCRATCH_END(scratch_audioDelayBuffer, INT_PCM, 1024);
805
0
  }
806
807
0
  return err;
808
0
}
809
810
/*-----------------------------------------------------------------------------
811
812
  functionname: WriteMetadataPayload
813
  description:  fills anc data and extension payload
814
  returns:      Error status
815
816
 ------------------------------------------------------------------------------*/
817
static FDK_METADATA_ERROR WriteMetadataPayload(
818
    const HANDLE_FDK_METADATA_ENCODER hMetaData,
819
0
    const AAC_METADATA* const pMetadata) {
820
0
  FDK_METADATA_ERROR err = METADATA_OK;
821
822
0
  if ((hMetaData == NULL) || (pMetadata == NULL)) {
823
0
    err = METADATA_INVALID_HANDLE;
824
0
    goto bail;
825
0
  }
826
827
0
  hMetaData->nExtensions = 0;
828
0
  hMetaData->matrix_mixdown_idx = -1;
829
830
0
  if (pMetadata->metadataMode != 0) {
831
    /* AAC-DRC */
832
0
    if ((pMetadata->metadataMode == 1) || (pMetadata->metadataMode == 2)) {
833
0
      hMetaData->exPayload[hMetaData->nExtensions].pData =
834
0
          hMetaData->drcInfoPayload;
835
0
      hMetaData->exPayload[hMetaData->nExtensions].dataType = EXT_DYNAMIC_RANGE;
836
0
      hMetaData->exPayload[hMetaData->nExtensions].associatedChElement = -1;
837
838
0
      hMetaData->exPayload[hMetaData->nExtensions].dataSize =
839
0
          WriteDynamicRangeInfoPayload(
840
0
              pMetadata, hMetaData->exPayload[hMetaData->nExtensions].pData);
841
842
0
      hMetaData->nExtensions++;
843
0
    } /* pMetadata->metadataMode==1 || pMetadata->metadataMode==2 */
844
845
    /* Matrix Mixdown Coefficient in PCE */
846
0
    if (pMetadata->WritePCEMixDwnIdx) {
847
0
      hMetaData->matrix_mixdown_idx =
848
0
          surmix2matrix_mixdown_idx[pMetadata->surroundMixLevel];
849
0
    }
850
851
    /* ETSI TS 101 154 (DVB) - MPEG4 ancillary_data() */
852
0
    if ((pMetadata->metadataMode == 2) ||
853
0
        (pMetadata->metadataMode == 3)) /* MP4_METADATA_MPEG_ETSI */
854
0
    {
855
0
      hMetaData->exPayload[hMetaData->nExtensions].pData =
856
0
          hMetaData->drcDsePayload;
857
0
      hMetaData->exPayload[hMetaData->nExtensions].dataType = EXT_DATA_ELEMENT;
858
0
      hMetaData->exPayload[hMetaData->nExtensions].associatedChElement = -1;
859
860
0
      hMetaData->exPayload[hMetaData->nExtensions].dataSize =
861
0
          WriteEtsiAncillaryDataPayload(
862
0
              pMetadata, hMetaData->exPayload[hMetaData->nExtensions].pData);
863
864
0
      hMetaData->nExtensions++;
865
0
    } /* metadataMode==2 || metadataMode==3 */
866
867
0
  } /* metadataMode != 0 */
868
869
0
bail:
870
0
  return err;
871
0
}
872
873
static INT WriteDynamicRangeInfoPayload(const AAC_METADATA* const pMetadata,
874
0
                                        UCHAR* const pExtensionPayload) {
875
0
  const INT pce_tag_present = 0; /* yet fixed setting! */
876
0
  const INT prog_ref_lev_res_bits = 0;
877
0
  INT i, drc_num_bands = 1;
878
879
0
  FDK_BITSTREAM bsWriter;
880
0
  FDKinitBitStream(&bsWriter, pExtensionPayload, 16, 0, BS_WRITER);
881
882
  /* dynamic_range_info() */
883
0
  FDKwriteBits(&bsWriter, pce_tag_present, 1); /* pce_tag_present */
884
0
  if (pce_tag_present) {
885
0
    FDKwriteBits(&bsWriter, 0x0, 4); /* pce_instance_tag */
886
0
    FDKwriteBits(&bsWriter, 0x0, 4); /* drc_tag_reserved_bits */
887
0
  }
888
889
  /* Exclude channels */
890
0
  FDKwriteBits(&bsWriter, (pMetadata->mpegDrc.excluded_chns_present) ? 1 : 0,
891
0
               1); /* excluded_chns_present*/
892
893
  /* Multiband DRC */
894
0
  FDKwriteBits(&bsWriter, (pMetadata->mpegDrc.drc_bands_present) ? 1 : 0,
895
0
               1); /* drc_bands_present */
896
0
  if (pMetadata->mpegDrc.drc_bands_present) {
897
0
    FDKwriteBits(&bsWriter, pMetadata->mpegDrc.drc_band_incr,
898
0
                 4); /* drc_band_incr */
899
0
    FDKwriteBits(&bsWriter, pMetadata->mpegDrc.drc_interpolation_scheme,
900
0
                 4); /* drc_interpolation_scheme */
901
0
    drc_num_bands += pMetadata->mpegDrc.drc_band_incr;
902
0
    for (i = 0; i < drc_num_bands; i++) {
903
0
      FDKwriteBits(&bsWriter, pMetadata->mpegDrc.drc_band_top[i],
904
0
                   8); /* drc_band_top */
905
0
    }
906
0
  }
907
908
  /* Program Reference Level */
909
0
  FDKwriteBits(&bsWriter, pMetadata->mpegDrc.prog_ref_level_present,
910
0
               1); /* prog_ref_level_present */
911
0
  if (pMetadata->mpegDrc.prog_ref_level_present) {
912
0
    FDKwriteBits(&bsWriter, pMetadata->mpegDrc.prog_ref_level,
913
0
                 7); /* prog_ref_level */
914
0
    FDKwriteBits(&bsWriter, prog_ref_lev_res_bits,
915
0
                 1); /* prog_ref_level_reserved_bits */
916
0
  }
917
918
  /* DRC Values */
919
0
  for (i = 0; i < drc_num_bands; i++) {
920
0
    FDKwriteBits(&bsWriter, (pMetadata->mpegDrc.dyn_rng_sgn[i]) ? 1 : 0,
921
0
                 1); /* dyn_rng_sgn[ */
922
0
    FDKwriteBits(&bsWriter, pMetadata->mpegDrc.dyn_rng_ctl[i],
923
0
                 7); /* dyn_rng_ctl */
924
0
  }
925
926
  /* return number of valid bits in extension payload. */
927
0
  return FDKgetValidBits(&bsWriter);
928
0
}
929
930
static INT WriteEtsiAncillaryDataPayload(const AAC_METADATA* const pMetadata,
931
0
                                         UCHAR* const pExtensionPayload) {
932
0
  FDK_BITSTREAM bsWriter;
933
0
  FDKinitBitStream(&bsWriter, pExtensionPayload, 16, 0, BS_WRITER);
934
935
  /* ancillary_data_sync */
936
0
  FDKwriteBits(&bsWriter, 0xBC, 8);
937
938
  /* bs_info */
939
0
  FDKwriteBits(&bsWriter, 0x3, 2); /* mpeg_audio_type */
940
0
  FDKwriteBits(&bsWriter, pMetadata->dolbySurroundMode,
941
0
               2); /* dolby_surround_mode */
942
0
  FDKwriteBits(&bsWriter, pMetadata->drcPresentationMode,
943
0
               2);                 /* DRC presentation mode */
944
0
  FDKwriteBits(&bsWriter, 0x0, 1); /* stereo_downmix_mode */
945
0
  FDKwriteBits(&bsWriter, 0x0, 1); /* reserved */
946
947
  /* ancillary_data_status */
948
0
  FDKwriteBits(&bsWriter, 0, 3); /* 3 bit Reserved, set to "0" */
949
0
  FDKwriteBits(&bsWriter, (pMetadata->DmxLvl_On) ? 1 : 0,
950
0
               1); /* downmixing_levels_MPEG4_status */
951
0
  FDKwriteBits(&bsWriter, pMetadata->etsiAncData.extAncDataStatus,
952
0
               1); /* ext_anc_data_status */
953
0
  FDKwriteBits(&bsWriter, (pMetadata->etsiAncData.compression_on) ? 1 : 0,
954
0
               1); /* audio_coding_mode_and_compression status */
955
0
  FDKwriteBits(&bsWriter,
956
0
               (pMetadata->etsiAncData.timecode_coarse_status) ? 1 : 0,
957
0
               1); /* coarse_grain_timecode_status */
958
0
  FDKwriteBits(&bsWriter, (pMetadata->etsiAncData.timecode_fine_status) ? 1 : 0,
959
0
               1); /* fine_grain_timecode_status */
960
961
  /* downmixing_levels_MPEG4_status */
962
0
  if (pMetadata->DmxLvl_On) {
963
0
    FDKwriteBits(
964
0
        &bsWriter,
965
0
        encodeDmxLvls(pMetadata->centerMixLevel, pMetadata->surroundMixLevel),
966
0
        8);
967
0
  }
968
969
  /* audio_coding_mode_and_compression_status */
970
0
  if (pMetadata->etsiAncData.compression_on) {
971
0
    FDKwriteBits(&bsWriter, 0x01, 8); /* audio coding mode */
972
0
    FDKwriteBits(&bsWriter, pMetadata->etsiAncData.compression_value,
973
0
                 8); /* compression value */
974
0
  }
975
976
  /* grain-timecode coarse/fine */
977
0
  if (pMetadata->etsiAncData.timecode_coarse_status) {
978
0
    FDKwriteBits(&bsWriter, 0x0, 16); /* not yet supported */
979
0
  }
980
981
0
  if (pMetadata->etsiAncData.timecode_fine_status) {
982
0
    FDKwriteBits(&bsWriter, 0x0, 16); /* not yet supported */
983
0
  }
984
985
  /* extended ancillary data structure */
986
0
  if (pMetadata->etsiAncData.extAncDataStatus) {
987
    /* ext_ancillary_data_status */
988
0
    FDKwriteBits(&bsWriter, 0, 1); /* Reserved, set to "0" */
989
0
    FDKwriteBits(&bsWriter,
990
0
                 pMetadata->etsiAncData.extAncData.ext_downmix_lvl_status,
991
0
                 1); /* ext_downmixing_levels_status */
992
0
    FDKwriteBits(&bsWriter,
993
0
                 pMetadata->etsiAncData.extAncData.ext_downmix_gain_status,
994
0
                 1); /* ext_downmixing_global_gains_status */
995
0
    FDKwriteBits(&bsWriter,
996
0
                 pMetadata->etsiAncData.extAncData.ext_lfe_downmix_status,
997
0
                 1);               /* ext_downmixing_lfe_level_status" */
998
0
    FDKwriteBits(&bsWriter, 0, 4); /* Reserved, set to "0" */
999
1000
    /* ext_downmixing_levels */
1001
0
    if (pMetadata->etsiAncData.extAncData.ext_downmix_lvl_status) {
1002
0
      FDKwriteBits(&bsWriter, pMetadata->etsiAncData.extAncData.ext_dmix_a_idx,
1003
0
                   3); /* dmix_a_idx */
1004
0
      FDKwriteBits(&bsWriter, pMetadata->etsiAncData.extAncData.ext_dmix_b_idx,
1005
0
                   3);               /* dmix_b_idx */
1006
0
      FDKwriteBits(&bsWriter, 0, 2); /* Reserved, set to "0" */
1007
0
    }
1008
1009
    /* ext_downmixing_gains */
1010
0
    if (pMetadata->etsiAncData.extAncData.ext_downmix_gain_status) {
1011
0
      FDKwriteBits(&bsWriter, pMetadata->etsiAncData.extAncData.dmx_gain_5_sgn,
1012
0
                   1); /* dmx_gain_5_sign */
1013
0
      FDKwriteBits(&bsWriter, pMetadata->etsiAncData.extAncData.dmx_gain_5_idx,
1014
0
                   6);               /* dmx_gain_5_idx */
1015
0
      FDKwriteBits(&bsWriter, 0, 1); /* Reserved, set to "0" */
1016
0
      FDKwriteBits(&bsWriter, pMetadata->etsiAncData.extAncData.dmx_gain_2_sgn,
1017
0
                   1); /* dmx_gain_2_sign */
1018
0
      FDKwriteBits(&bsWriter, pMetadata->etsiAncData.extAncData.dmx_gain_2_idx,
1019
0
                   6);               /* dmx_gain_2_idx */
1020
0
      FDKwriteBits(&bsWriter, 0, 1); /* Reserved, set to "0" */
1021
0
    }
1022
1023
0
    if (pMetadata->etsiAncData.extAncData.ext_lfe_downmix_status) {
1024
0
      FDKwriteBits(&bsWriter,
1025
0
                   pMetadata->etsiAncData.extAncData.ext_dmix_lfe_idx,
1026
0
                   4);               /* dmix_lfe_idx */
1027
0
      FDKwriteBits(&bsWriter, 0, 4); /* Reserved, set to "0" */
1028
0
    }
1029
0
  }
1030
1031
0
  return FDKgetValidBits(&bsWriter);
1032
0
}
1033
1034
static FDK_METADATA_ERROR LoadSubmittedMetadata(
1035
    const AACENC_MetaData* const hMetadata, const INT nChannels,
1036
0
    const INT metadataMode, AAC_METADATA* const pAacMetaData) {
1037
0
  FDK_METADATA_ERROR err = METADATA_OK;
1038
1039
0
  if (pAacMetaData == NULL) {
1040
0
    err = METADATA_INVALID_HANDLE;
1041
0
  } else {
1042
    /* init struct */
1043
0
    FDKmemclear(pAacMetaData, sizeof(AAC_METADATA));
1044
1045
0
    if (hMetadata != NULL) {
1046
      /* convert data */
1047
0
      pAacMetaData->mpegDrc.drc_profile = hMetadata->drc_profile;
1048
0
      pAacMetaData->etsiAncData.comp_profile = hMetadata->comp_profile;
1049
0
      pAacMetaData->mpegDrc.drc_TargetRefLevel = hMetadata->drc_TargetRefLevel;
1050
0
      pAacMetaData->etsiAncData.comp_TargetRefLevel =
1051
0
          hMetadata->comp_TargetRefLevel;
1052
0
      pAacMetaData->mpegDrc.prog_ref_level_present =
1053
0
          hMetadata->prog_ref_level_present;
1054
0
      pAacMetaData->mpegDrc.prog_ref_level =
1055
0
          dialnorm2progreflvl(hMetadata->prog_ref_level);
1056
1057
0
      pAacMetaData->centerMixLevel = hMetadata->centerMixLevel;
1058
0
      pAacMetaData->surroundMixLevel = hMetadata->surroundMixLevel;
1059
0
      pAacMetaData->WritePCEMixDwnIdx = hMetadata->PCE_mixdown_idx_present;
1060
0
      pAacMetaData->DmxLvl_On = hMetadata->ETSI_DmxLvl_present;
1061
1062
0
      pAacMetaData->etsiAncData.compression_on =
1063
0
          (hMetadata->comp_profile == AACENC_METADATA_DRC_NOT_PRESENT ? 0 : 1);
1064
1065
0
      if (pAacMetaData->mpegDrc.drc_profile ==
1066
0
          AACENC_METADATA_DRC_NOT_PRESENT) {
1067
0
        pAacMetaData->mpegDrc.drc_profile =
1068
0
            AACENC_METADATA_DRC_NONE; /* MPEG DRC gains are
1069
                                         always present in BS
1070
                                         syntax */
1071
        /* we should give a warning, but ErrorHandler does not support this */
1072
0
      }
1073
1074
0
      if (nChannels == 2) {
1075
0
        pAacMetaData->dolbySurroundMode =
1076
0
            hMetadata->dolbySurroundMode; /* dolby_surround_mode */
1077
0
      } else {
1078
0
        pAacMetaData->dolbySurroundMode = 0;
1079
0
      }
1080
1081
0
      pAacMetaData->drcPresentationMode = hMetadata->drcPresentationMode;
1082
      /* override external values if DVB DRC presentation mode is given */
1083
0
      if (pAacMetaData->drcPresentationMode == 1) {
1084
0
        pAacMetaData->mpegDrc.drc_TargetRefLevel =
1085
0
            fMax(-(31 << 16), pAacMetaData->mpegDrc.drc_TargetRefLevel);
1086
0
        pAacMetaData->etsiAncData.comp_TargetRefLevel = fMax(
1087
0
            -(20 << 16),
1088
0
            pAacMetaData->etsiAncData.comp_TargetRefLevel); /* implies -23dB */
1089
0
      }
1090
0
      if (pAacMetaData->drcPresentationMode == 2) {
1091
0
        pAacMetaData->mpegDrc.drc_TargetRefLevel =
1092
0
            fMax(-(23 << 16), pAacMetaData->mpegDrc.drc_TargetRefLevel);
1093
0
        pAacMetaData->etsiAncData.comp_TargetRefLevel =
1094
0
            fMax(-(23 << 16), pAacMetaData->etsiAncData.comp_TargetRefLevel);
1095
0
      }
1096
0
      if (pAacMetaData->etsiAncData.comp_profile ==
1097
0
          AACENC_METADATA_DRC_NOT_PRESENT) {
1098
        /* DVB defines to revert to Light DRC if heavy is not present */
1099
0
        if (pAacMetaData->drcPresentationMode != 0) {
1100
          /* we exclude the "not indicated" mode as this requires the user to
1101
           * define desired levels anyway */
1102
0
          pAacMetaData->mpegDrc.drc_TargetRefLevel =
1103
0
              fMax(pAacMetaData->etsiAncData.comp_TargetRefLevel,
1104
0
                   pAacMetaData->mpegDrc.drc_TargetRefLevel);
1105
0
        }
1106
0
      }
1107
1108
0
      pAacMetaData->etsiAncData.timecode_coarse_status =
1109
0
          0; /* not yet supported - attention: Update
1110
                GetEstMetadataBytesPerFrame() if enable this! */
1111
0
      pAacMetaData->etsiAncData.timecode_fine_status =
1112
0
          0; /* not yet supported - attention: Update
1113
                GetEstMetadataBytesPerFrame() if enable this! */
1114
1115
      /* extended ancillary data */
1116
0
      pAacMetaData->etsiAncData.extAncDataStatus =
1117
0
          ((hMetadata->ExtMetaData.extAncDataEnable == 1) ? 1 : 0);
1118
1119
0
      if (pAacMetaData->etsiAncData.extAncDataStatus) {
1120
0
        pAacMetaData->etsiAncData.extAncData.ext_downmix_lvl_status =
1121
0
            (hMetadata->ExtMetaData.extDownmixLevelEnable ? 1 : 0);
1122
0
        pAacMetaData->etsiAncData.extAncData.ext_downmix_gain_status =
1123
0
            (hMetadata->ExtMetaData.dmxGainEnable ? 1 : 0);
1124
0
        pAacMetaData->etsiAncData.extAncData.ext_lfe_downmix_status =
1125
0
            (hMetadata->ExtMetaData.lfeDmxEnable ? 1 : 0);
1126
1127
0
        pAacMetaData->etsiAncData.extAncData.ext_dmix_a_idx =
1128
0
            hMetadata->ExtMetaData.extDownmixLevel_A;
1129
0
        pAacMetaData->etsiAncData.extAncData.ext_dmix_b_idx =
1130
0
            hMetadata->ExtMetaData.extDownmixLevel_B;
1131
1132
0
        if (pAacMetaData->etsiAncData.extAncData.ext_downmix_gain_status) {
1133
0
          encodeDynrng(hMetadata->ExtMetaData.dmxGain5,
1134
0
                       &(pAacMetaData->etsiAncData.extAncData.dmx_gain_5_idx),
1135
0
                       &(pAacMetaData->etsiAncData.extAncData.dmx_gain_5_sgn));
1136
0
          encodeDynrng(hMetadata->ExtMetaData.dmxGain2,
1137
0
                       &(pAacMetaData->etsiAncData.extAncData.dmx_gain_2_idx),
1138
0
                       &(pAacMetaData->etsiAncData.extAncData.dmx_gain_2_sgn));
1139
0
        } else {
1140
0
          encodeDynrng(1 << 16,
1141
0
                       &(pAacMetaData->etsiAncData.extAncData.dmx_gain_5_idx),
1142
0
                       &(pAacMetaData->etsiAncData.extAncData.dmx_gain_5_sgn));
1143
0
          encodeDynrng(1 << 16,
1144
0
                       &(pAacMetaData->etsiAncData.extAncData.dmx_gain_2_idx),
1145
0
                       &(pAacMetaData->etsiAncData.extAncData.dmx_gain_2_sgn));
1146
0
        }
1147
1148
0
        if (pAacMetaData->etsiAncData.extAncData.ext_lfe_downmix_status) {
1149
0
          pAacMetaData->etsiAncData.extAncData.ext_dmix_lfe_idx =
1150
0
              hMetadata->ExtMetaData.lfeDmxLevel;
1151
0
        } else {
1152
0
          pAacMetaData->etsiAncData.extAncData.ext_dmix_lfe_idx =
1153
0
              15; /* -inf dB */
1154
0
        }
1155
0
      } else {
1156
0
        pAacMetaData->etsiAncData.extAncData.ext_downmix_lvl_status = 0;
1157
0
        pAacMetaData->etsiAncData.extAncData.ext_downmix_gain_status = 0;
1158
0
        pAacMetaData->etsiAncData.extAncData.ext_lfe_downmix_status = 0;
1159
1160
0
        pAacMetaData->etsiAncData.extAncData.ext_dmix_a_idx = 7; /* -inf dB */
1161
0
        pAacMetaData->etsiAncData.extAncData.ext_dmix_b_idx = 7; /* -inf dB */
1162
1163
0
        encodeDynrng(1 << 16,
1164
0
                     &(pAacMetaData->etsiAncData.extAncData.dmx_gain_5_idx),
1165
0
                     &(pAacMetaData->etsiAncData.extAncData.dmx_gain_5_sgn));
1166
0
        encodeDynrng(1 << 16,
1167
0
                     &(pAacMetaData->etsiAncData.extAncData.dmx_gain_2_idx),
1168
0
                     &(pAacMetaData->etsiAncData.extAncData.dmx_gain_2_sgn));
1169
1170
0
        pAacMetaData->etsiAncData.extAncData.ext_dmix_lfe_idx =
1171
0
            15; /* -inf dB */
1172
0
      }
1173
1174
0
      pAacMetaData->metadataMode = metadataMode;
1175
0
    } else {
1176
0
      pAacMetaData->metadataMode = 0; /* there is no configuration available */
1177
0
    }
1178
0
  }
1179
1180
0
  return err;
1181
0
}
1182
1183
0
INT FDK_MetadataEnc_GetDelay(HANDLE_FDK_METADATA_ENCODER hMetadataEnc) {
1184
0
  INT delay = 0;
1185
1186
0
  if (hMetadataEnc != NULL) {
1187
0
    delay = hMetadataEnc->nAudioDataDelay;
1188
0
  }
1189
1190
0
  return delay;
1191
0
}