1438 lines · 54.1 KB · C
RawDownload
/* * AAC encoder * Copyright (C) 2008 Konstantin Shishkov * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /** * @file * AAC encoder */ /*********************************** *              TODOs: * add sane pulse detection ***********************************/#include <float.h> #include "libavutil/channel_layout.h"#include "libavutil/libm.h"#include "libavutil/float_dsp.h"#include "libavutil/mem.h"#include "libavutil/opt.h"#include "avcodec.h"#include "codec_internal.h"#include "encode.h"#include "put_bits.h"#include "mpeg4audio.h"#include "sinewin.h"#include "profiles.h"#include "version.h" #include "aac.h"#include "aactab.h"#include "aacenc.h"#include "aacenctab.h"#include "aacenc_utils.h" #include "psymodel.h" /** * List of PCE (Program Configuration Element) for the channel layouts listed * in channel_layout.h * * For those wishing in the future to add other layouts: * * - num_ele: number of elements in each group of front, side, back, lfe channels *            (an element is of type SCE (single channel), CPE (channel pair) for *            the first 3 groups; and is LFE for LFE group). * * - pairing: 0 for an SCE element or 1 for a CPE; does not apply to LFE group * * - index: there are three independent indices for SCE, CPE and LFE; *     they are incremented irrespective of the group to which the element belongs; *     they are not reset when going from one group to another * *     Example: for 7.0 channel layout, *        .pairing = { { 1, 0 }, { 1 }, { 1 }, }, (3 CPE and 1 SCE in front group) *        .index = { { 0, 0 }, { 1 }, { 2 }, }, *               (index is 0 for the single SCE but goes from 0 to 2 for the CPEs) * *     The index order impacts the channel ordering. But is otherwise arbitrary *     (the sequence could have been 2, 0, 1 instead of 0, 1, 2). * *     Spec allows for discontinuous indices, e.g. if one has a total of two SCE, *     SCE.0 SCE.15 is OK per spec; BUT it won't be decoded by our AAC decoder *     which at this time requires that indices fully cover some range starting *     from 0 (SCE.1 SCE.0 is OK but not SCE.0 SCE.15). * * - config_map: total number of elements and their types. Beware, the way the *               types are ordered impacts the final channel ordering. * * - reorder_map: reorders the channels. * */static const AACPCEInfo aac_pce_configs[] = {    {        .layout = AV_CHANNEL_LAYOUT_MONO,        .num_ele = { 1, 0, 0, 0 },        .pairing = { { 0 }, },        .index = { { 0 }, },        .config_map = { 1, TYPE_SCE, },        .reorder_map = { 0 },    },    {        .layout = AV_CHANNEL_LAYOUT_STEREO,        .num_ele = { 1, 0, 0, 0 },        .pairing = { { 1 }, },        .index = { { 0 }, },        .config_map = { 1, TYPE_CPE, },        .reorder_map = { 0, 1 },    },    {        .layout = AV_CHANNEL_LAYOUT_2POINT1,        .num_ele = { 1, 0, 0, 1 },        .pairing = { { 1 }, },        .index = { { 0 },{ 0 },{ 0 },{ 0 } },        .config_map = { 2, TYPE_CPE, TYPE_LFE },        .reorder_map = { 0, 1, 2 },    },    {        .layout = AV_CHANNEL_LAYOUT_2_1,        .num_ele = { 1, 0, 1, 0 },        .pairing = { { 1 },{ 0 },{ 0 } },        .index = { { 0 },{ 0 },{ 0 }, },        .config_map = { 2, TYPE_CPE, TYPE_SCE },        .reorder_map = { 0, 1, 2 },    },    {        .layout = AV_CHANNEL_LAYOUT_SURROUND,        .num_ele = { 2, 0, 0, 0 },        .pairing = { { 1, 0 }, },        .index = { { 0, 0 }, },        .config_map = { 2, TYPE_CPE, TYPE_SCE, },        .reorder_map = { 0, 1, 2 },    },    {        .layout = AV_CHANNEL_LAYOUT_3POINT1,        .num_ele = { 2, 0, 0, 1 },        .pairing = { { 1, 0 }, },        .index = { { 0, 0 }, { 0 }, { 0 }, { 0 }, },        .config_map = { 3, TYPE_CPE, TYPE_SCE, TYPE_LFE },        .reorder_map = { 0, 1, 2, 3 },    },    {        .layout = AV_CHANNEL_LAYOUT_4POINT0,        .num_ele = { 2, 0, 1, 0 },        .pairing = { { 1, 0 }, { 0 }, { 0 }, },        .index = { { 0, 0 }, { 0 }, { 1 } },        .config_map = { 3, TYPE_CPE, TYPE_SCE, TYPE_SCE },        .reorder_map = {  0, 1, 2, 3 },    },    {        .layout = AV_CHANNEL_LAYOUT_4POINT1,        .num_ele = { 2, 1, 1, 0 },        .pairing = { { 1, 0 }, { 0 }, { 0 }, },        .index = { { 0, 0 }, { 1 }, { 2 }, { 0 } },        .config_map = { 4, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_SCE },        .reorder_map = { 0, 1, 2, 3, 4 },    },    {        .layout = AV_CHANNEL_LAYOUT_2_2,        .num_ele = { 1, 1, 0, 0 },        .pairing = { { 1 }, { 1 }, },        .index = { { 0 }, { 1 }, },        .config_map = { 2, TYPE_CPE, TYPE_CPE },        .reorder_map = { 0, 1, 2, 3 },    },    {        .layout = AV_CHANNEL_LAYOUT_QUAD,        .num_ele = { 1, 0, 1, 0 },        .pairing = { { 1 }, { 0 }, { 1 }, },        .index = { { 0 }, { 0 }, { 1 } },        .config_map = { 2, TYPE_CPE, TYPE_CPE },        .reorder_map = { 0, 1, 2, 3 },    },    {        .layout = AV_CHANNEL_LAYOUT_5POINT0,        .num_ele = { 2, 1, 0, 0 },        .pairing = { { 1, 0 }, { 1 }, },        .index = { { 0, 0 }, { 1 } },        .config_map = { 3, TYPE_CPE, TYPE_SCE, TYPE_CPE },        .reorder_map = { 0, 1, 2, 3, 4 },    },    {        .layout = AV_CHANNEL_LAYOUT_5POINT1,        .num_ele = { 2, 1, 1, 0 },        .pairing = { { 1, 0 }, { 0 }, { 1 }, },        .index = { { 0, 0 }, { 1 }, { 1 } },        .config_map = { 4, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_CPE },        .reorder_map = { 0, 1, 2, 3, 4, 5 },    },    {        .layout = AV_CHANNEL_LAYOUT_5POINT0_BACK,        .num_ele = { 2, 0, 1, 0 },        .pairing = { { 1, 0 }, { 0 }, { 1 } },        .index = { { 0, 0 }, { 0 }, { 1 } },        .config_map = { 3, TYPE_CPE, TYPE_SCE, TYPE_CPE },        .reorder_map = { 0, 1, 2, 3, 4 },    },    {        .layout = AV_CHANNEL_LAYOUT_5POINT1_BACK,        .num_ele = { 2, 1, 1, 0 },        .pairing = { { 1, 0 }, { 0 }, { 1 }, },        .index = { { 0, 0 }, { 1 }, { 1 } },        .config_map = { 4, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_CPE },        .reorder_map = { 0, 1, 2, 3, 4, 5 },    },    {        .layout = AV_CHANNEL_LAYOUT_6POINT0,        .num_ele = { 2, 1, 1, 0 },        .pairing = { { 1, 0 }, { 1 }, { 0 }, },        .index = { { 0, 0 }, { 1 }, { 1 } },        .config_map = { 4, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_SCE },        .reorder_map = { 0, 1, 2, 3, 4, 5 },    },    {        .layout = AV_CHANNEL_LAYOUT_6POINT0_FRONT,        .num_ele = { 2, 1, 0, 0 },        .pairing = { { 1, 1 }, { 1 } },        .index = { { 1, 0 }, { 2 }, },        .config_map = { 3, TYPE_CPE, TYPE_CPE, TYPE_CPE, },        .reorder_map = { 0, 1, 2, 3, 4, 5 },    },    {        .layout = AV_CHANNEL_LAYOUT_HEXAGONAL,        .num_ele = { 2, 0, 2, 0 },        .pairing = { { 1, 0 },{ 0 },{ 1, 0 }, },        .index = { { 0, 0 },{ 0 },{ 1, 1 } },        .config_map = { 4, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_SCE, },        .reorder_map = { 0, 1, 2, 3, 4, 5 },    },    {        .layout = AV_CHANNEL_LAYOUT_6POINT1,        .num_ele = { 2, 1, 2, 0 },        .pairing = { { 1, 0 },{ 0 },{ 1, 0 }, },        .index = { { 0, 0 },{ 1 },{ 1, 2 } },        .config_map = { 5, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_CPE, TYPE_SCE },        .reorder_map = { 0, 1, 2, 3, 4, 5, 6 },    },    {        .layout = AV_CHANNEL_LAYOUT_6POINT1_BACK,        .num_ele = { 2, 1, 2, 0 },        .pairing = { { 1, 0 }, { 0 }, { 1, 0 }, },        .index = { { 0, 0 }, { 1 }, { 1, 2 } },        .config_map = { 5, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_CPE, TYPE_SCE },        .reorder_map = { 0, 1, 2, 3, 4, 5, 6 },    },    {        .layout = AV_CHANNEL_LAYOUT_6POINT1_FRONT,        .num_ele = { 2, 1, 2, 0 },        .pairing = { { 1, 0 }, { 0 }, { 1, 0 }, },        .index = { { 0, 0 }, { 1 }, { 1, 2 } },        .config_map = { 5, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_CPE, TYPE_SCE },        .reorder_map = { 0, 1, 2, 3, 4, 5, 6 },    },    {        .layout = AV_CHANNEL_LAYOUT_7POINT0,        .num_ele = { 2, 1, 1, 0 },        .pairing = { { 1, 0 }, { 1 }, { 1 }, },        .index = { { 0, 0 }, { 1 }, { 2 }, },        .config_map = { 4, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_CPE },        .reorder_map = { 0, 1, 2, 3, 4, 5, 6 },    },    {        .layout = AV_CHANNEL_LAYOUT_7POINT0_FRONT,        .num_ele = { 2, 1, 1, 0 },        .pairing = { { 1, 0 }, { 1 }, { 1 }, },        .index = { { 0, 0 }, { 1 }, { 2 }, },        .config_map = { 4, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_CPE },        .reorder_map = { 0, 1, 2, 3, 4, 5, 6 },    },    {        .layout = AV_CHANNEL_LAYOUT_7POINT1,        .num_ele = { 2, 1, 2, 0 },        .pairing = { { 1, 0 }, { 0 }, { 1, 1 }, },        .index = { { 0, 0 }, { 1 }, { 1, 2 }, { 0 } },        .config_map = { 5, TYPE_CPE, TYPE_SCE,  TYPE_SCE, TYPE_CPE, TYPE_CPE },        .reorder_map = { 0, 1, 2, 3, 4, 5, 6, 7 },    },    {        .layout = AV_CHANNEL_LAYOUT_7POINT1_WIDE,        .num_ele = { 2, 1, 2, 0 },        .pairing = { { 1, 0 }, { 0 },{  1, 1 }, },        .index = { { 0, 0 }, { 1 }, { 1, 2 }, { 0 } },        .config_map = { 5, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_CPE, TYPE_CPE },        .reorder_map = { 0, 1, 2, 3, 4, 5, 6, 7 },    },    {        .layout = AV_CHANNEL_LAYOUT_7POINT1_WIDE_BACK,        .num_ele = { 2, 1, 2, 0 },        .pairing = { { 1, 0 }, { 0 }, { 1, 1 }, },        .index = { { 0, 0 }, { 1 }, { 1, 2 }, { 0 } },        .config_map = { 5, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_CPE, TYPE_CPE },        .reorder_map = { 0, 1, 2, 3, 4, 5, 6, 7 },    },    {        .layout = AV_CHANNEL_LAYOUT_OCTAGONAL,        .num_ele = { 2, 1, 2, 0 },        .pairing = { { 1, 0 }, { 1 }, { 1, 0 }, },        .index = { { 0, 0 }, { 1 }, { 2, 1 } },        .config_map = { 5, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_CPE, TYPE_SCE },        .reorder_map = { 0, 1, 2, 3, 4, 5, 6, 7 },    },    {   /* Meant for order 2/mixed ambisonics */        .layout = { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 9,                    .u.mask = AV_CH_LAYOUT_OCTAGONAL | AV_CH_TOP_CENTER },        .num_ele = { 2, 2, 2, 0 },        .pairing = { { 1, 0 }, { 1, 0 }, { 1, 0 }, },        .index = { { 0, 0 }, { 1, 1 }, { 2, 2 } },        .config_map = { 6, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_SCE },        .reorder_map = { 0, 1, 2, 3, 4, 5, 6, 7, 8 },    },    {   /* Meant for order 2/mixed ambisonics */        .layout = { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 10,                    .u.mask = AV_CH_LAYOUT_6POINT0_FRONT | AV_CH_BACK_CENTER |                              AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT | AV_CH_TOP_CENTER },        .num_ele = { 2, 2, 2, 0 },        .pairing = { { 1, 1 }, { 1, 0 }, { 1, 0 }, },        .index = { { 0, 1 }, { 2, 0 }, { 3, 1 } },        .config_map = { 6, TYPE_CPE, TYPE_CPE, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_SCE },        .reorder_map = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },    },    {        .layout = AV_CHANNEL_LAYOUT_HEXADECAGONAL,        .num_ele = { 4, 2, 4, 0 },        .pairing = { { 1, 0, 1, 0 }, { 1, 1 }, { 1, 0, 1, 0 }, },        .index = { { 0, 0, 1, 1 }, { 2, 3 }, { 4, 2, 5, 3 } },        .config_map = { 10, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_CPE, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_SCE },        .reorder_map = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },    },}; static void put_pce(PutBitContext *pb, AVCodecContext *avctx){    int i, j;    AACEncContext *s = avctx->priv_data;    AACPCEInfo *pce = &s->pce;    const int bitexact = avctx->flags & AV_CODEC_FLAG_BITEXACT;    const char *aux_data = bitexact ? "Lavc" : LIBAVCODEC_IDENT;     put_bits(pb, 4, 0);     put_bits(pb, 2, avctx->profile);    put_bits(pb, 4, s->samplerate_index);     put_bits(pb, 4, pce->num_ele[0]); /* Front */    put_bits(pb, 4, pce->num_ele[1]); /* Side */    put_bits(pb, 4, pce->num_ele[2]); /* Back */    put_bits(pb, 2, pce->num_ele[3]); /* LFE */    put_bits(pb, 3, 0); /* Assoc data */    put_bits(pb, 4, 0); /* CCs */     put_bits(pb, 1, 0); /* Stereo mixdown */    put_bits(pb, 1, 0); /* Mono mixdown */    put_bits(pb, 1, 0); /* Something else */     for (i = 0; i < 4; i++) {        for (j = 0; j < pce->num_ele[i]; j++) {            if (i < 3)                put_bits(pb, 1, pce->pairing[i][j]);            put_bits(pb, 4, pce->index[i][j]);        }    }     align_put_bits(pb);    put_bits(pb, 8, strlen(aux_data));    ff_put_string(pb, aux_data, 0);} /** * Make AAC audio config object. * @see 1.6.2.1 "Syntax - AudioSpecificConfig" */static int put_audio_specific_config(AVCodecContext *avctx){    PutBitContext pb;    AACEncContext *s = avctx->priv_data;    int channels = (!s->needs_pce)*(s->channels - (s->channels == 8 ? 1 : 0));    const int max_size = 32;     avctx->extradata = av_mallocz(max_size);    if (!avctx->extradata)        return AVERROR(ENOMEM);     init_put_bits(&pb, avctx->extradata, max_size);    put_bits(&pb, 5, s->profile+1); //profile    put_bits(&pb, 4, s->samplerate_index); //sample rate index    put_bits(&pb, 4, channels);    //GASpecificConfig    put_bits(&pb, 1, 0); //frame length - 1024 samples    put_bits(&pb, 1, 0); //does not depend on core coder    put_bits(&pb, 1, 0); //is not extension    if (s->needs_pce)        put_pce(&pb, avctx);     //Explicitly Mark SBR absent    put_bits(&pb, 11, 0x2b7); //sync extension    put_bits(&pb, 5,  AOT_SBR);    put_bits(&pb, 1,  0);    flush_put_bits(&pb);    avctx->extradata_size = put_bytes_output(&pb);     return 0;} void ff_quantize_band_cost_cache_init(struct AACEncContext *s){    ++s->quantize_band_cost_cache_generation;    if (s->quantize_band_cost_cache_generation == 0) {        memset(s->quantize_band_cost_cache, 0, sizeof(s->quantize_band_cost_cache));        s->quantize_band_cost_cache_generation = 1;    }} #define WINDOW_FUNC(type) \static void apply_ ##type ##_window(AVFloatDSPContext *fdsp, \                                    SingleChannelElement *sce, \                                    const float *audio) WINDOW_FUNC(only_long){    const float *lwindow = sce->ics.use_kb_window[0] ? ff_aac_kbd_long_1024 : ff_sine_1024;    const float *pwindow = sce->ics.use_kb_window[1] ? ff_aac_kbd_long_1024 : ff_sine_1024;    float *out = sce->ret_buf;     fdsp->vector_fmul        (out,        audio,        lwindow, 1024);    fdsp->vector_fmul_reverse(out + 1024, audio + 1024, pwindow, 1024);} WINDOW_FUNC(long_start){    const float *lwindow = sce->ics.use_kb_window[1] ? ff_aac_kbd_long_1024 : ff_sine_1024;    const float *swindow = sce->ics.use_kb_window[0] ? ff_aac_kbd_short_128 : ff_sine_128;    float *out = sce->ret_buf;     fdsp->vector_fmul(out, audio, lwindow, 1024);    memcpy(out + 1024, audio + 1024, sizeof(out[0]) * 448);    fdsp->vector_fmul_reverse(out + 1024 + 448, audio + 1024 + 448, swindow, 128);    memset(out + 1024 + 576, 0, sizeof(out[0]) * 448);} WINDOW_FUNC(long_stop){    const float *lwindow = sce->ics.use_kb_window[0] ? ff_aac_kbd_long_1024 : ff_sine_1024;    const float *swindow = sce->ics.use_kb_window[1] ? ff_aac_kbd_short_128 : ff_sine_128;    float *out = sce->ret_buf;     memset(out, 0, sizeof(out[0]) * 448);    fdsp->vector_fmul(out + 448, audio + 448, swindow, 128);    memcpy(out + 576, audio + 576, sizeof(out[0]) * 448);    fdsp->vector_fmul_reverse(out + 1024, audio + 1024, lwindow, 1024);} WINDOW_FUNC(eight_short){    const float *swindow = sce->ics.use_kb_window[0] ? ff_aac_kbd_short_128 : ff_sine_128;    const float *pwindow = sce->ics.use_kb_window[1] ? ff_aac_kbd_short_128 : ff_sine_128;    const float *in = audio + 448;    float *out = sce->ret_buf;    int w;     for (w = 0; w < 8; w++) {        fdsp->vector_fmul        (out, in, w ? pwindow : swindow, 128);        out += 128;        in  += 128;        fdsp->vector_fmul_reverse(out, in, swindow, 128);        out += 128;    }} static void (*const apply_window[4])(AVFloatDSPContext *fdsp,                                     SingleChannelElement *sce,                                     const float *audio) = {    [ONLY_LONG_SEQUENCE]   = apply_only_long_window,    [LONG_START_SEQUENCE]  = apply_long_start_window,    [EIGHT_SHORT_SEQUENCE] = apply_eight_short_window,    [LONG_STOP_SEQUENCE]   = apply_long_stop_window}; static void apply_window_and_mdct(AACEncContext *s, SingleChannelElement *sce,                                  float *audio){    int i;    float *output = sce->ret_buf;     apply_window[sce->ics.window_sequence[0]](s->fdsp, sce, audio);     if (sce->ics.window_sequence[0] != EIGHT_SHORT_SEQUENCE)        s->mdct1024_fn(s->mdct1024, sce->coeffs, output, sizeof(float));    else        for (i = 0; i < 1024; i += 128)            s->mdct128_fn(s->mdct128, &sce->coeffs[i], output + i*2, sizeof(float));    memcpy(audio, audio + 1024, sizeof(audio[0]) * 1024);    memcpy(sce->pcoeffs, sce->coeffs, sizeof(sce->pcoeffs));} /** * Encode ics_info element. * @see Table 4.6 (syntax of ics_info) */static void put_ics_info(AACEncContext *s, IndividualChannelStream *info){    int w;     put_bits(&s->pb, 1, 0);                // ics_reserved bit

Lines 1–500 of 1438.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t