X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Flibfdk-aacenc.c;h=2cea58f152e11c7f16065ed7de31cc68d3c09481;hb=4628443ca3534060888dd0015b229337eac13fd2;hp=c9ecc4c1c6c6de47b3c6911bdb3443e0bbc76ea8;hpb=e6153f173a49e5bfa70b0c04d2f82930533597b9;p=ffmpeg diff --git a/libavcodec/libfdk-aacenc.c b/libavcodec/libfdk-aacenc.c index c9ecc4c1c6c..2cea58f152e 100644 --- a/libavcodec/libfdk-aacenc.c +++ b/libavcodec/libfdk-aacenc.c @@ -4,29 +4,27 @@ * * This file is part of Libav. * - * Libav 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. + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * Libav 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 Libav; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include +#include "libavutil/channel_layout.h" +#include "libavutil/common.h" +#include "libavutil/opt.h" #include "avcodec.h" #include "audio_frame_queue.h" #include "internal.h" -#include "libavutil/audioconvert.h" -#include "libavutil/common.h" -#include "libavutil/opt.h" typedef struct AACContext { const AVClass *class; @@ -36,6 +34,7 @@ typedef struct AACContext { int signaling; int latm; int header_period; + int vbr; AudioFrameQueue afq; } AACContext; @@ -50,6 +49,7 @@ static const AVOption aac_enc_options[] = { { "explicit_hierarchical", "Explicit hierarchical signaling", 0, AV_OPT_TYPE_CONST, { .i64 = 2 }, 0, 0, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM, "signaling" }, { "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 }, { "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 }, + { "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 }, { NULL } }; @@ -95,9 +95,6 @@ static int aac_encode_close(AVCodecContext *avctx) if (s->handle) aacEncClose(&s->handle); -#if FF_API_OLD_ENCODE_AUDIO - av_freep(&avctx->coded_frame); -#endif av_freep(&avctx->extradata); ff_af_queue_close(&s->afq); @@ -152,6 +149,20 @@ static av_cold int aac_encode_init(AVCodecContext *avctx) case 4: mode = MODE_1_2_1; sce = 2; cpe = 1; break; case 5: mode = MODE_1_2_2; sce = 1; cpe = 2; break; case 6: mode = MODE_1_2_2_1; sce = 2; cpe = 2; break; +/* The version macro is introduced the same time as the 7.1 support, so this + should suffice. */ +#ifdef AACENCODER_LIB_VL0 + case 8: + sce = 2; + cpe = 3; + if (avctx->channel_layout == AV_CH_LAYOUT_7POINT1) { + mode = MODE_7_1_REAR_SURROUND; + } else { + // MODE_1_2_2_2_1 and MODE_7_1_FRONT_CENTER use the same channel layout + mode = MODE_7_1_FRONT_CENTER; + } + break; +#endif default: av_log(avctx, AV_LOG_ERROR, "Unsupported number of channels %d\n", avctx->channels); @@ -173,13 +184,16 @@ static av_cold int aac_encode_init(AVCodecContext *avctx) goto error; } - if (avctx->flags & CODEC_FLAG_QSCALE) { - int mode = avctx->global_quality; + if (avctx->flags & AV_CODEC_FLAG_QSCALE || s->vbr) { + int mode = s->vbr ? s->vbr : avctx->global_quality; if (mode < 1 || mode > 5) { av_log(avctx, AV_LOG_WARNING, "VBR quality %d out of range, should be 1-5\n", mode); mode = av_clip(mode, 1, 5); } + av_log(avctx, AV_LOG_WARNING, + "Note, the VBR setting is unsupported and only works with " + "some parameter combinations\n"); if ((err = aacEncoder_SetParam(s->handle, AACENC_BITRATEMODE, mode)) != AACENC_OK) { av_log(avctx, AV_LOG_ERROR, "Unable to set the VBR bitrate mode %d: %s\n", @@ -195,6 +209,7 @@ static av_cold int aac_encode_init(AVCodecContext *avctx) avctx->bit_rate = (96*sce + 128*cpe) * avctx->sample_rate / 44; if (avctx->profile == FF_PROFILE_AAC_HE || avctx->profile == FF_PROFILE_AAC_HE_V2 || + avctx->profile == FF_PROFILE_MPEG2_AAC_HE || s->eld_sbr) avctx->bit_rate /= 2; } @@ -209,7 +224,7 @@ static av_cold int aac_encode_init(AVCodecContext *avctx) /* Choose bitstream format - if global header is requested, use * raw access units, otherwise use ADTS. */ if ((err = aacEncoder_SetParam(s->handle, AACENC_TRANSMUX, - avctx->flags & CODEC_FLAG_GLOBAL_HEADER ? 0 : s->latm ? 10 : 2)) != AACENC_OK) { + avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER ? 0 : s->latm ? 10 : 2)) != AACENC_OK) { av_log(avctx, AV_LOG_ERROR, "Unable to set the transmux format: %s\n", aac_get_error(err)); goto error; @@ -228,7 +243,7 @@ static av_cold int aac_encode_init(AVCodecContext *avctx) * if using mp4 mode (raw access units, with global header) and * implicit signaling if using ADTS. */ if (s->signaling < 0) - s->signaling = avctx->flags & CODEC_FLAG_GLOBAL_HEADER ? 2 : 0; + s->signaling = avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER ? 2 : 0; if ((err = aacEncoder_SetParam(s->handle, AACENC_SIGNALING_MODE, s->signaling)) != AACENC_OK) { @@ -245,14 +260,14 @@ static av_cold int aac_encode_init(AVCodecContext *avctx) } if (avctx->cutoff > 0) { - if (avctx->cutoff < (avctx->sample_rate + 255) >> 8) { + if (avctx->cutoff < (avctx->sample_rate + 255) >> 8 || avctx->cutoff > 20000) { av_log(avctx, AV_LOG_ERROR, "cutoff valid range is %d-20000\n", (avctx->sample_rate + 255) >> 8); goto error; } if ((err = aacEncoder_SetParam(s->handle, AACENC_BANDWIDTH, avctx->cutoff)) != AACENC_OK) { - av_log(avctx, AV_LOG_ERROR, "Unable to set the encoder bandwith to %d: %s\n", + av_log(avctx, AV_LOG_ERROR, "Unable to set the encoder bandwidth to %d: %s\n", avctx->cutoff, aac_get_error(err)); goto error; } @@ -270,21 +285,14 @@ static av_cold int aac_encode_init(AVCodecContext *avctx) goto error; } -#if FF_API_OLD_ENCODE_AUDIO - avctx->coded_frame = avcodec_alloc_frame(); - if (!avctx->coded_frame) { - ret = AVERROR(ENOMEM); - goto error; - } -#endif avctx->frame_size = info.frameLength; - avctx->delay = info.encoderDelay; + avctx->initial_padding = info.encoderDelay; ff_af_queue_init(avctx, &s->afq); - if (avctx->flags & CODEC_FLAG_GLOBAL_HEADER) { + if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) { avctx->extradata_size = info.confSize; avctx->extradata = av_mallocz(avctx->extradata_size + - FF_INPUT_BUFFER_PADDING_SIZE); + AV_INPUT_BUFFER_PADDING_SIZE); if (!avctx->extradata) { ret = AVERROR(ENOMEM); goto error; @@ -329,7 +337,7 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, in_buf.bufElSizes = &in_buffer_element_size; /* add current frame to the queue */ - if ((ret = ff_af_queue_add(&s->afq, frame) < 0)) + if ((ret = ff_af_queue_add(&s->afq, frame)) < 0) return ret; } @@ -390,23 +398,33 @@ static const uint64_t aac_channel_layout[] = { AV_CH_LAYOUT_4POINT0, AV_CH_LAYOUT_5POINT0_BACK, AV_CH_LAYOUT_5POINT1_BACK, +#ifdef AACENCODER_LIB_VL0 + AV_CH_LAYOUT_7POINT1_WIDE_BACK, + AV_CH_LAYOUT_7POINT1, +#endif 0, }; +static const int aac_sample_rates[] = { + 96000, 88200, 64000, 48000, 44100, 32000, + 24000, 22050, 16000, 12000, 11025, 8000, 0 +}; + AVCodec ff_libfdk_aac_encoder = { - .name = "libfdk_aac", - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_AAC, - .priv_data_size = sizeof(AACContext), - .init = aac_encode_init, - .encode2 = aac_encode_frame, - .close = aac_encode_close, - .capabilities = CODEC_CAP_SMALL_LAST_FRAME | CODEC_CAP_DELAY, - .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, - AV_SAMPLE_FMT_NONE }, - .long_name = NULL_IF_CONFIG_SMALL("Fraunhofer FDK AAC"), - .priv_class = &aac_enc_class, - .defaults = aac_encode_defaults, - .profiles = profiles, - .channel_layouts = aac_channel_layout, + .name = "libfdk_aac", + .long_name = NULL_IF_CONFIG_SMALL("Fraunhofer FDK AAC"), + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_AAC, + .priv_data_size = sizeof(AACContext), + .init = aac_encode_init, + .encode2 = aac_encode_frame, + .close = aac_encode_close, + .capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME | AV_CODEC_CAP_DELAY, + .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, + AV_SAMPLE_FMT_NONE }, + .priv_class = &aac_enc_class, + .defaults = aac_encode_defaults, + .profiles = profiles, + .supported_samplerates = aac_sample_rates, + .channel_layouts = aac_channel_layout, };