Coverage Report

Created: 2026-04-01 07:42

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ffmpeg/libavcodec/libfdk-aacenc.c
Line
Count
Source
1
/*
2
 * AAC encoder wrapper
3
 * Copyright (c) 2012 Martin Storsjo
4
 *
5
 * This file is part of FFmpeg.
6
 *
7
 * Permission to use, copy, modify, and/or distribute this software for any
8
 * purpose with or without fee is hereby granted, provided that the above
9
 * copyright notice and this permission notice appear in all copies.
10
 *
11
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
 */
19
20
#include <fdk-aac/aacenc_lib.h>
21
22
#include "libavutil/channel_layout.h"
23
#include "libavutil/common.h"
24
#include "libavutil/intreadwrite.h"
25
#include "libavutil/mem.h"
26
#include "libavutil/opt.h"
27
#include "avcodec.h"
28
#include "audio_frame_queue.h"
29
#include "codec_internal.h"
30
#include "encode.h"
31
#include "profiles.h"
32
33
#ifdef AACENCODER_LIB_VL0
34
#define FDKENC_VER_AT_LEAST(vl0, vl1) \
35
    ((AACENCODER_LIB_VL0 > vl0) || \
36
     (AACENCODER_LIB_VL0 == vl0 && AACENCODER_LIB_VL1 >= vl1))
37
#else
38
#define FDKENC_VER_AT_LEAST(vl0, vl1) 0
39
#endif
40
41
typedef struct AACContext {
42
    const AVClass *class;
43
    HANDLE_AACENCODER handle;
44
    int afterburner;
45
    int eld_sbr;
46
    int eld_v2;
47
    int signaling;
48
    int latm;
49
    int header_period;
50
    int vbr;
51
    int drc_profile;
52
    int drc_target_ref;
53
    int comp_profile;
54
    int comp_target_ref;
55
    int prog_ref;
56
    int metadata_mode;
57
    AACENC_MetaData metaDataSetup;
58
    int delay_sent;
59
    int frame_length;
60
61
    AudioFrameQueue afq;
62
} AACContext;
63
64
static const AVOption aac_enc_options[] = {
65
    { "afterburner", "Afterburner (improved quality)", offsetof(AACContext, afterburner), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM },
66
    { "eld_sbr", "Enable SBR for ELD (for SBR in other configurations, use the -profile parameter)", offsetof(AACContext, eld_sbr), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM },
67
#if FDKENC_VER_AT_LEAST(4, 0) // 4.0.0
68
    { "eld_v2", "Enable ELDv2 (LD-MPS extension for ELD stereo signals)", offsetof(AACContext, eld_v2), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM },
69
#endif
70
    { "signaling", "SBR/PS signaling style", offsetof(AACContext, signaling), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 2, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM, .unit = "signaling" },
71
    { "default", "Choose signaling implicitly (explicit hierarchical by default, implicit if global header is disabled)", 0, AV_OPT_TYPE_CONST, { .i64 = -1 }, 0, 0, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM, .unit = "signaling" },
72
    { "implicit", "Implicit backwards compatible signaling", 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, 0, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM, .unit = "signaling" },
73
    { "explicit_sbr", "Explicit SBR, implicit PS signaling", 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM, .unit = "signaling" },
74
    { "explicit_hierarchical", "Explicit hierarchical signaling", 0, AV_OPT_TYPE_CONST, { .i64 = 2 }, 0, 0, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM, .unit = "signaling" },
75
    { "latm", "Output LATM/LOAS encapsulated data", offsetof(AACContext, latm), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM },
76
    { "header_period", "StreamMuxConfig and PCE repetition period (in frames)", offsetof(AACContext, header_period), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 0xffff, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM },
77
    { "vbr", "VBR mode (1-5)", offsetof(AACContext, vbr), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 5, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM },
78
    { "drc_profile", "The desired compression profile for AAC DRC", offsetof(AACContext, drc_profile), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 256, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM },
79
    { "drc_target_ref", "Expected target reference level at decoder side in dB (for clipping prevention/limiter)", offsetof(AACContext, drc_target_ref), AV_OPT_TYPE_INT, { .i64 = 0.0 }, -31.75, 0, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM },
80
    { "comp_profile", "The desired compression profile for AAC DRC", offsetof(AACContext, comp_profile), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 256, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM },
81
    { "comp_target_ref", "Expected target reference level at decoder side in dB (for clipping prevention/limiter)", offsetof(AACContext, comp_target_ref), AV_OPT_TYPE_INT, { .i64 = 0.0 }, -31.75, 0, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM },
82
    { "prog_ref", "The program reference level or dialog level in dB", offsetof(AACContext, prog_ref), AV_OPT_TYPE_INT, { .i64 = 0.0 }, -31.75, 0, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM },
83
    { "frame_length", "The desired frame length", offsetof(AACContext, frame_length), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1024, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM },
84
    FF_AAC_PROFILE_OPTS
85
    { NULL }
86
};
87
88
static const AVClass aac_enc_class = {
89
    .class_name = "libfdk_aac",
90
    .item_name  = av_default_item_name,
91
    .option     = aac_enc_options,
92
    .version    = LIBAVUTIL_VERSION_INT,
93
};
94
95
static const char *aac_get_error(AACENC_ERROR err)
96
0
{
97
0
    switch (err) {
98
0
    case AACENC_OK:
99
0
        return "No error";
100
0
    case AACENC_INVALID_HANDLE:
101
0
        return "Invalid handle";
102
0
    case AACENC_MEMORY_ERROR:
103
0
        return "Memory allocation error";
104
0
    case AACENC_UNSUPPORTED_PARAMETER:
105
0
        return "Unsupported parameter";
106
0
    case AACENC_INVALID_CONFIG:
107
0
        return "Invalid config";
108
0
    case AACENC_INIT_ERROR:
109
0
        return "Initialization error";
110
0
    case AACENC_INIT_AAC_ERROR:
111
0
        return "AAC library initialization error";
112
0
    case AACENC_INIT_SBR_ERROR:
113
0
        return "SBR library initialization error";
114
0
    case AACENC_INIT_TP_ERROR:
115
0
        return "Transport library initialization error";
116
0
    case AACENC_INIT_META_ERROR:
117
0
        return "Metadata library initialization error";
118
0
    case AACENC_ENCODE_ERROR:
119
0
        return "Encoding error";
120
0
    case AACENC_ENCODE_EOF:
121
0
        return "End of file";
122
0
    default:
123
0
        return "Unknown error";
124
0
    }
125
0
}
126
127
static int aac_encode_close(AVCodecContext *avctx)
128
0
{
129
0
    AACContext *s = avctx->priv_data;
130
131
0
    if (s->handle)
132
0
        aacEncClose(&s->handle);
133
0
    ff_af_queue_close(&s->afq);
134
135
0
    return 0;
136
0
}
137
138
static void aac_encode_flush(AVCodecContext *avctx)
139
0
{
140
0
    AACContext *s = avctx->priv_data;
141
0
    AACENC_BufDesc in_buf   = { 0 }, out_buf = { 0 };
142
0
    AACENC_InArgs  in_args  = { 0 };
143
0
    AACENC_OutArgs out_args;
144
0
    int64_t pts, duration;
145
0
    uint8_t dummy_in[1], dummy_out[1];
146
0
    int in_buffer_identifiers[] = { IN_AUDIO_DATA, IN_METADATA_SETUP };
147
0
    int in_buffer_element_sizes[] = { 2, sizeof(AACENC_MetaData) };
148
0
    int in_buffer_sizes[] = { 0, sizeof(s->metaDataSetup) };
149
0
    int out_buffer_identifier = OUT_BITSTREAM_DATA;
150
0
    int out_buffer_size = sizeof(dummy_out), out_buffer_element_size = 1;
151
0
    void* inBuffer[] = { dummy_in, &s->metaDataSetup };
152
0
    void *out_ptr = dummy_out;
153
0
    AACENC_ERROR err;
154
155
0
    ff_af_queue_remove(&s->afq, s->afq.frame_count, &pts, &duration);
156
157
0
    in_buf.bufs              = (void **)inBuffer;
158
0
    in_buf.numBufs           = s->metadata_mode == 0 ? 1 : 2;
159
0
    in_buf.bufferIdentifiers = in_buffer_identifiers;
160
0
    in_buf.bufSizes          = in_buffer_sizes;
161
0
    in_buf.bufElSizes        = in_buffer_element_sizes;
162
163
0
    out_buf.numBufs           = 1;
164
0
    out_buf.bufs              = &out_ptr;
165
0
    out_buf.bufferIdentifiers = &out_buffer_identifier;
166
0
    out_buf.bufSizes          = &out_buffer_size;
167
0
    out_buf.bufElSizes        = &out_buffer_element_size;
168
169
0
    err = aacEncEncode(s->handle, &in_buf, &out_buf, &in_args, &out_args);
170
0
    if (err != AACENC_OK) {
171
0
        av_log(avctx, AV_LOG_ERROR, "Unexpected error while flushing: %s\n",
172
0
               aac_get_error(err));
173
0
    }
174
0
}
175
176
static av_cold int aac_encode_init(AVCodecContext *avctx)
177
0
{
178
0
    AACContext *s = avctx->priv_data;
179
0
    int ret = AVERROR(EINVAL);
180
0
    AACENC_InfoStruct info = { 0 };
181
0
    AVCPBProperties *cpb_props;
182
0
    CHANNEL_MODE mode;
183
0
    AACENC_ERROR err;
184
0
    int aot = AV_PROFILE_AAC_LOW + 1;
185
0
    int sce = 0, cpe = 0;
186
187
0
    if ((err = aacEncOpen(&s->handle, 0, avctx->ch_layout.nb_channels)) != AACENC_OK) {
188
0
        av_log(avctx, AV_LOG_ERROR, "Unable to open the encoder: %s\n",
189
0
               aac_get_error(err));
190
0
        goto error;
191
0
    }
192
193
0
    if (avctx->profile != AV_PROFILE_UNKNOWN)
194
0
        aot = avctx->profile + 1;
195
196
0
    if ((err = aacEncoder_SetParam(s->handle, AACENC_AOT, aot)) != AACENC_OK) {
197
0
        av_log(avctx, AV_LOG_ERROR, "Unable to set the AOT %d: %s\n",
198
0
               aot, aac_get_error(err));
199
0
        goto error;
200
0
    }
201
202
0
    if (aot == AV_PROFILE_AAC_ELD + 1 && s->eld_sbr) {
203
0
        if ((err = aacEncoder_SetParam(s->handle, AACENC_SBR_MODE,
204
0
                                       1)) != AACENC_OK) {
205
0
            av_log(avctx, AV_LOG_ERROR, "Unable to enable SBR for ELD: %s\n",
206
0
                   aac_get_error(err));
207
0
            goto error;
208
0
        }
209
0
    }
210
211
0
    if (s->frame_length >= 0) {
212
0
        if ((err = aacEncoder_SetParam(s->handle, AACENC_GRANULE_LENGTH,
213
0
                                       s->frame_length)) != AACENC_OK) {
214
0
            av_log(avctx, AV_LOG_ERROR, "Unable to set granule length: %s\n",
215
0
                   aac_get_error(err));
216
0
            goto error;
217
0
        }
218
0
    }
219
220
0
    if ((err = aacEncoder_SetParam(s->handle, AACENC_SAMPLERATE,
221
0
                                   avctx->sample_rate)) != AACENC_OK) {
222
0
        av_log(avctx, AV_LOG_ERROR, "Unable to set the sample rate %d: %s\n",
223
0
               avctx->sample_rate, aac_get_error(err));
224
0
        goto error;
225
0
    }
226
227
0
    switch (avctx->ch_layout.nb_channels) {
228
0
    case 1: mode = MODE_1;       sce = 1; cpe = 0; break;
229
0
    case 2:
230
#if FDKENC_VER_AT_LEAST(4, 0) // 4.0.0
231
      // (profile + 1) to map from profile range to AOT range
232
0
      if (aot == AV_PROFILE_AAC_ELD + 1 && s->eld_v2) {
233
0
          if ((err = aacEncoder_SetParam(s->handle, AACENC_CHANNELMODE,
234
0
                                         128)) != AACENC_OK) {
235
0
              av_log(avctx, AV_LOG_ERROR, "Unable to enable ELDv2: %s\n",
236
0
                     aac_get_error(err));
237
0
              goto error;
238
0
          } else {
239
0
            mode = MODE_212;
240
0
            sce = 1;
241
0
            cpe = 0;
242
0
          }
243
0
      } else
244
0
#endif
245
0
      {
246
0
        mode = MODE_2;
247
0
        sce = 0;
248
0
        cpe = 1;
249
0
      }
250
0
      break;
251
0
    case 3: mode = MODE_1_2;     sce = 1; cpe = 1; break;
252
0
    case 4: mode = MODE_1_2_1;   sce = 2; cpe = 1; break;
253
0
    case 5: mode = MODE_1_2_2;   sce = 1; cpe = 2; break;
254
0
    case 6: mode = MODE_1_2_2_1; sce = 2; cpe = 2; break;
255
#if FDKENC_VER_AT_LEAST(4, 0) // 4.0.0
256
0
    case 7: mode = MODE_6_1;     sce = 3; cpe = 2; break;
257
0
#endif
258
/* The version macro is introduced the same time as the 7.1 support, so this
259
   should suffice. */
260
#if FDKENC_VER_AT_LEAST(3, 4) // 3.4.12
261
0
    case 8:
262
0
        sce = 2;
263
0
        cpe = 3;
264
0
        if (!av_channel_layout_compare(&avctx->ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_7POINT1)) {
265
0
            mode = MODE_7_1_REAR_SURROUND;
266
#if FDKENC_VER_AT_LEAST(4, 0) // 4.0.0
267
0
        } else if (!av_channel_layout_compare(&avctx->ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_7POINT1_TOP_BACK)) {
268
0
            mode = MODE_7_1_TOP_FRONT;
269
0
#endif
270
0
        } else {
271
            // MODE_1_2_2_2_1 and MODE_7_1_FRONT_CENTER use the same channel layout
272
0
            mode = MODE_7_1_FRONT_CENTER;
273
0
        }
274
0
        break;
275
0
#endif
276
0
    default:
277
0
        av_log(avctx, AV_LOG_ERROR,
278
0
               "Unsupported number of channels %d\n", avctx->ch_layout.nb_channels);
279
0
        goto error;
280
0
    }
281
282
0
    if ((err = aacEncoder_SetParam(s->handle, AACENC_CHANNELMODE,
283
0
                                   mode)) != AACENC_OK) {
284
0
        av_log(avctx, AV_LOG_ERROR,
285
0
               "Unable to set channel mode %d: %s\n", mode, aac_get_error(err));
286
0
        goto error;
287
0
    }
288
289
0
    if ((err = aacEncoder_SetParam(s->handle, AACENC_CHANNELORDER,
290
0
                                   1)) != AACENC_OK) {
291
0
        av_log(avctx, AV_LOG_ERROR,
292
0
               "Unable to set wav channel order %d: %s\n",
293
0
               mode, aac_get_error(err));
294
0
        goto error;
295
0
    }
296
297
0
    if (avctx->flags & AV_CODEC_FLAG_QSCALE || s->vbr) {
298
0
        int mode = s->vbr ? s->vbr : avctx->global_quality;
299
0
        if (mode <  1 || mode > 5) {
300
0
            av_log(avctx, AV_LOG_WARNING,
301
0
                   "VBR quality %d out of range, should be 1-5\n", mode);
302
0
            mode = av_clip(mode, 1, 5);
303
0
        }
304
0
        av_log(avctx, AV_LOG_WARNING,
305
0
               "Note, the VBR setting is unsupported and only works with "
306
0
               "some parameter combinations\n");
307
0
        if ((err = aacEncoder_SetParam(s->handle, AACENC_BITRATEMODE,
308
0
                                       mode)) != AACENC_OK) {
309
0
            av_log(avctx, AV_LOG_ERROR, "Unable to set the VBR bitrate mode %d: %s\n",
310
0
                   mode, aac_get_error(err));
311
0
            goto error;
312
0
        }
313
0
    } else {
314
0
        if (avctx->bit_rate <= 0) {
315
0
            if (avctx->profile == AV_PROFILE_AAC_HE_V2) {
316
0
                sce = 1;
317
0
                cpe = 0;
318
0
            }
319
0
            avctx->bit_rate = (96*sce + 128*cpe) * avctx->sample_rate / 44;
320
0
            if (avctx->profile == AV_PROFILE_AAC_HE ||
321
0
                avctx->profile == AV_PROFILE_AAC_HE_V2 ||
322
0
                avctx->profile == AV_PROFILE_MPEG2_AAC_HE ||
323
0
                s->eld_sbr)
324
0
                avctx->bit_rate /= 2;
325
0
        }
326
0
        if ((err = aacEncoder_SetParam(s->handle, AACENC_BITRATE,
327
0
                                       avctx->bit_rate)) != AACENC_OK) {
328
0
            av_log(avctx, AV_LOG_ERROR, "Unable to set the bitrate %"PRId64": %s\n",
329
0
                   avctx->bit_rate, aac_get_error(err));
330
0
            goto error;
331
0
        }
332
0
    }
333
334
    /* Choose bitstream format - if global header is requested, use
335
     * raw access units, otherwise use ADTS. */
336
0
    if ((err = aacEncoder_SetParam(s->handle, AACENC_TRANSMUX,
337
0
                                   avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER ? TT_MP4_RAW :
338
0
                                   s->latm ? TT_MP4_LOAS : TT_MP4_ADTS)) != AACENC_OK) {
339
0
        av_log(avctx, AV_LOG_ERROR, "Unable to set the transmux format: %s\n",
340
0
               aac_get_error(err));
341
0
        goto error;
342
0
    }
343
344
0
    if (s->latm && s->header_period) {
345
0
        if ((err = aacEncoder_SetParam(s->handle, AACENC_HEADER_PERIOD,
346
0
                                       s->header_period)) != AACENC_OK) {
347
0
             av_log(avctx, AV_LOG_ERROR, "Unable to set header period: %s\n",
348
0
                    aac_get_error(err));
349
0
             goto error;
350
0
        }
351
0
    }
352
353
    /* If no signaling mode is chosen, use explicit hierarchical signaling
354
     * if using mp4 mode (raw access units, with global header) and
355
     * implicit signaling if using ADTS. */
356
0
    if (s->signaling < 0)
357
0
        s->signaling = avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER ? 2 : 0;
358
359
0
    if ((err = aacEncoder_SetParam(s->handle, AACENC_SIGNALING_MODE,
360
0
                                   s->signaling)) != AACENC_OK) {
361
0
        av_log(avctx, AV_LOG_ERROR, "Unable to set signaling mode %d: %s\n",
362
0
               s->signaling, aac_get_error(err));
363
0
        goto error;
364
0
    }
365
366
0
    if ((err = aacEncoder_SetParam(s->handle, AACENC_AFTERBURNER,
367
0
                                   s->afterburner)) != AACENC_OK) {
368
0
        av_log(avctx, AV_LOG_ERROR, "Unable to set afterburner to %d: %s\n",
369
0
               s->afterburner, aac_get_error(err));
370
0
        goto error;
371
0
    }
372
373
0
    if (avctx->cutoff > 0) {
374
0
        if (avctx->cutoff < (avctx->sample_rate + 255) >> 8 || avctx->cutoff > 20000) {
375
0
            av_log(avctx, AV_LOG_ERROR, "cutoff valid range is %d-20000\n",
376
0
                   (avctx->sample_rate + 255) >> 8);
377
0
            goto error;
378
0
        }
379
0
        if ((err = aacEncoder_SetParam(s->handle, AACENC_BANDWIDTH,
380
0
                                       avctx->cutoff)) != AACENC_OK) {
381
0
            av_log(avctx, AV_LOG_ERROR, "Unable to set the encoder bandwidth to %d: %s\n",
382
0
                   avctx->cutoff, aac_get_error(err));
383
0
            goto error;
384
0
        }
385
0
    }
386
387
0
    s->metadata_mode = 0;
388
0
    if (s->prog_ref) {
389
0
        s->metadata_mode = 1;
390
0
        s->metaDataSetup.prog_ref_level_present = 1;
391
0
        s->metaDataSetup.prog_ref_level = s->prog_ref << 16;
392
0
    }
393
0
    if (s->drc_profile) {
394
0
        s->metadata_mode = 1;
395
0
        s->metaDataSetup.drc_profile = s->drc_profile;
396
0
        s->metaDataSetup.drc_TargetRefLevel = s->drc_target_ref << 16;
397
0
        if (s->comp_profile) {
398
            /* Including the comp_profile means that we need to set the mode to ETSI */
399
0
            s->metadata_mode = 2;
400
0
            s->metaDataSetup.comp_profile = s->comp_profile;
401
0
            s->metaDataSetup.comp_TargetRefLevel = s->comp_target_ref << 16;
402
0
        }
403
0
    }
404
405
0
    if ((err = aacEncoder_SetParam(s->handle, AACENC_METADATA_MODE, s->metadata_mode)) != AACENC_OK) {
406
0
        av_log(avctx, AV_LOG_ERROR, "Unable to set metadata mode to %d: %s\n",
407
0
                s->metadata_mode, aac_get_error(err));
408
0
        goto error;
409
0
    }
410
411
0
    if ((err = aacEncEncode(s->handle, NULL, NULL, NULL, NULL)) != AACENC_OK) {
412
0
        av_log(avctx, AV_LOG_ERROR, "Unable to initialize the encoder: %s\n",
413
0
               aac_get_error(err));
414
0
        return AVERROR(EINVAL);
415
0
    }
416
417
0
    if ((err = aacEncInfo(s->handle, &info)) != AACENC_OK) {
418
0
        av_log(avctx, AV_LOG_ERROR, "Unable to get encoder info: %s\n",
419
0
               aac_get_error(err));
420
0
        goto error;
421
0
    }
422
423
0
    avctx->frame_size = info.frameLength;
424
#if FDKENC_VER_AT_LEAST(4, 0) // 4.0.0
425
0
    avctx->initial_padding = info.nDelay;
426
#else
427
    avctx->initial_padding = info.encoderDelay;
428
#endif
429
0
    ff_af_queue_init(avctx, &s->afq);
430
431
0
    if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) {
432
0
        avctx->extradata_size = info.confSize;
433
0
        avctx->extradata      = av_mallocz(avctx->extradata_size +
434
0
                                           AV_INPUT_BUFFER_PADDING_SIZE);
435
0
        if (!avctx->extradata) {
436
0
            ret = AVERROR(ENOMEM);
437
0
            goto error;
438
0
        }
439
440
0
        memcpy(avctx->extradata, info.confBuf, info.confSize);
441
0
    }
442
443
0
    cpb_props = ff_encode_add_cpb_side_data(avctx);
444
0
    if (!cpb_props)
445
0
        return AVERROR(ENOMEM);
446
0
    cpb_props->max_bitrate =
447
0
    cpb_props->min_bitrate =
448
0
    cpb_props->avg_bitrate = avctx->bit_rate;
449
450
0
    return 0;
451
0
error:
452
0
    aac_encode_close(avctx);
453
0
    return ret;
454
0
}
455
456
static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
457
                            const AVFrame *frame, int *got_packet_ptr)
458
0
{
459
0
    AACContext    *s        = avctx->priv_data;
460
0
    AACENC_BufDesc in_buf   = { 0 }, out_buf = { 0 };
461
0
    AACENC_InArgs  in_args  = { 0 };
462
0
    AACENC_OutArgs out_args = { 0 };
463
0
    void* inBuffer[] = { 0, &s->metaDataSetup };
464
0
    int in_buffer_identifiers[] = { IN_AUDIO_DATA, IN_METADATA_SETUP };
465
0
    int in_buffer_element_sizes[] = { 2, sizeof(AACENC_MetaData) };
466
0
    int in_buffer_sizes[] = { 0, sizeof(s->metaDataSetup) };
467
0
    int out_buffer_identifier = OUT_BITSTREAM_DATA;
468
0
    int out_buffer_size, out_buffer_element_size;
469
0
    void *out_ptr;
470
0
    int ret, discard_padding;
471
0
    uint8_t dummy_buf[1];
472
0
    AACENC_ERROR err;
473
474
    /* handle end-of-stream small frame and flushing */
475
0
    if (!frame) {
476
        /* Must be a non-null pointer, even if it's a dummy. We could use
477
         * the address of anything else on the stack as well. */
478
0
        inBuffer[0]          = dummy_buf;
479
480
0
        in_args.numInSamples = -1;
481
0
    } else {
482
0
        inBuffer[0]          = frame->data[0];
483
0
        in_buffer_sizes[0]   = 2 * avctx->ch_layout.nb_channels * frame->nb_samples;
484
485
0
        in_args.numInSamples = avctx->ch_layout.nb_channels * frame->nb_samples;
486
487
        /* add current frame to the queue */
488
0
        if ((ret = ff_af_queue_add(&s->afq, frame)) < 0)
489
0
            return ret;
490
0
    }
491
492
0
    if (s->metadata_mode == 0) {
493
0
        in_buf.numBufs       = 1;
494
0
    } else {
495
0
        in_buf.numBufs       = 2;
496
0
    }
497
498
0
    in_buf.bufs              = (void**)inBuffer;
499
0
    in_buf.bufferIdentifiers = in_buffer_identifiers;
500
0
    in_buf.bufSizes          = in_buffer_sizes;
501
0
    in_buf.bufElSizes        = in_buffer_element_sizes;
502
503
    /* The maximum packet size is 6144 bits aka 768 bytes per channel. */
504
0
    ret = ff_alloc_packet(avctx, avpkt, FFMAX(8192, 768 * avctx->ch_layout.nb_channels));
505
0
    if (ret < 0)
506
0
        return ret;
507
508
0
    out_ptr                   = avpkt->data;
509
0
    out_buffer_size           = avpkt->size;
510
0
    out_buffer_element_size   = 1;
511
0
    out_buf.numBufs           = 1;
512
0
    out_buf.bufs              = &out_ptr;
513
0
    out_buf.bufferIdentifiers = &out_buffer_identifier;
514
0
    out_buf.bufSizes          = &out_buffer_size;
515
0
    out_buf.bufElSizes        = &out_buffer_element_size;
516
517
0
    if ((err = aacEncEncode(s->handle, &in_buf, &out_buf, &in_args,
518
0
                            &out_args)) != AACENC_OK) {
519
0
        if (!frame && err == AACENC_ENCODE_EOF)
520
0
            return 0;
521
0
        av_log(avctx, AV_LOG_ERROR, "Unable to encode frame: %s\n",
522
0
               aac_get_error(err));
523
0
        return AVERROR(EINVAL);
524
0
    }
525
526
0
    if (!out_args.numOutBytes)
527
0
        return 0;
528
529
    /* Get the next frame pts & duration */
530
0
    ff_af_queue_remove(&s->afq, avctx->frame_size, &avpkt->pts,
531
0
                       &avpkt->duration);
532
533
0
    discard_padding = avctx->frame_size - ff_samples_from_time_base(avctx, avpkt->duration);
534
    // Check if subtraction resulted in an overflow
535
0
    if ((discard_padding < avctx->frame_size) != (avpkt->duration > 0)) {
536
0
        av_log(avctx, AV_LOG_ERROR, "discard padding overflow\n");
537
0
        return AVERROR(EINVAL);
538
0
    }
539
0
    if ((!s->delay_sent && avctx->initial_padding > 0) || discard_padding > 0) {
540
0
        uint8_t *side_data =
541
0
            av_packet_new_side_data(avpkt, AV_PKT_DATA_SKIP_SAMPLES, 10);
542
0
        if (!side_data)
543
0
            return AVERROR(ENOMEM);
544
0
        if (!s->delay_sent) {
545
0
            AV_WL32(side_data, avctx->initial_padding);
546
0
            s->delay_sent = 1;
547
0
        }
548
0
        AV_WL32(side_data + 4, discard_padding);
549
0
    }
550
551
0
    avpkt->size     = out_args.numOutBytes;
552
0
    avpkt->flags   |= AV_PKT_FLAG_KEY;
553
0
    *got_packet_ptr = 1;
554
0
    return 0;
555
0
}
556
557
static const AVProfile profiles[] = {
558
    { AV_PROFILE_AAC_LOW,   "LC"       },
559
    { AV_PROFILE_AAC_HE,    "HE-AAC"   },
560
    { AV_PROFILE_AAC_HE_V2, "HE-AACv2" },
561
    { AV_PROFILE_AAC_LD,    "LD"       },
562
    { AV_PROFILE_AAC_ELD,   "ELD"      },
563
    { AV_PROFILE_UNKNOWN },
564
};
565
566
static const FFCodecDefault aac_encode_defaults[] = {
567
    { "b", "0" },
568
    { NULL }
569
};
570
571
static const AVChannelLayout aac_ch_layouts[16] = {
572
    AV_CHANNEL_LAYOUT_MONO,
573
    AV_CHANNEL_LAYOUT_STEREO,
574
    AV_CHANNEL_LAYOUT_SURROUND,
575
    AV_CHANNEL_LAYOUT_4POINT0,
576
    AV_CHANNEL_LAYOUT_5POINT0_BACK,
577
    AV_CHANNEL_LAYOUT_5POINT1_BACK,
578
#if FDKENC_VER_AT_LEAST(4, 0) // 4.0.0
579
    AV_CHANNEL_LAYOUT_6POINT1_BACK,
580
#endif
581
#if FDKENC_VER_AT_LEAST(3, 4) // 3.4.12
582
    AV_CHANNEL_LAYOUT_7POINT1_WIDE_BACK,
583
    AV_CHANNEL_LAYOUT_7POINT1,
584
#endif
585
#if FDKENC_VER_AT_LEAST(4, 0) // 4.0.0
586
    AV_CHANNEL_LAYOUT_7POINT1_TOP_BACK,
587
#endif
588
    { 0 },
589
};
590
591
static const int aac_sample_rates[] = {
592
    96000, 88200, 64000, 48000, 44100, 32000,
593
    24000, 22050, 16000, 12000, 11025, 8000, 0
594
};
595
596
const FFCodec ff_libfdk_aac_encoder = {
597
    .p.name                = "libfdk_aac",
598
    CODEC_LONG_NAME("Fraunhofer FDK AAC"),
599
    .p.type                = AVMEDIA_TYPE_AUDIO,
600
    .p.id                  = AV_CODEC_ID_AAC,
601
    .p.capabilities        = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY |
602
                             AV_CODEC_CAP_ENCODER_FLUSH |
603
                             AV_CODEC_CAP_SMALL_LAST_FRAME,
604
    .caps_internal         = FF_CODEC_CAP_NOT_INIT_THREADSAFE,
605
    .priv_data_size        = sizeof(AACContext),
606
    .init                  = aac_encode_init,
607
    FF_CODEC_ENCODE_CB(aac_encode_frame),
608
    .flush                 = aac_encode_flush,
609
    .close                 = aac_encode_close,
610
    CODEC_SAMPLEFMTS(AV_SAMPLE_FMT_S16),
611
    .p.priv_class          = &aac_enc_class,
612
    .defaults              = aac_encode_defaults,
613
    .p.profiles            = profiles,
614
    CODEC_SAMPLERATES_ARRAY(aac_sample_rates),
615
    .p.wrapper_name        = "libfdk",
616
    CODEC_CH_LAYOUTS_ARRAY(aac_ch_layouts),
617
};