Compare commits

...
Sign in to create a new pull request.

29 commits

Author SHA1 Message Date
wrapper
55a0abdad0 fix extra data 2025-09-06 12:02:16 +07:00
wrapper
0050f855c3 s16 only ffmpeg patch 2025-08-25 09:40:20 +07:00
wrapper
71d5253fc5 sbr fix 2 2025-08-24 14:32:55 +07:00
wrapper
ef95c58ba8 sbr readjust 2025-08-24 09:51:56 +07:00
wrapper
3f57d16826 int to bool 2025-08-22 20:37:49 +07:00
wrapper
118cf93d99 force dual rate 2025-08-22 20:22:00 +07:00
wrapper
939c17a0d8 flush must be called 2 times 2025-08-21 23:13:59 +07:00
wrapper
93e8e929ba fix channel enumerate bug 2025-08-18 22:28:36 +07:00
wrapper
b6c2951529 fix overrun 2025-08-18 21:49:53 +07:00
wrapper
a5d2e4f584 work on static lib 2025-08-18 20:48:28 +07:00
wrapper
65f200b87f update git 2025-08-18 16:46:35 +07:00
wrapper
23b6b30870 finally 2025-08-15 14:23:23 +07:00
wrapper
084af3e6f0 new patch, new externals 2025-08-15 13:32:34 +07:00
wrapper
07efeec79f new git patch 2025-08-14 20:36:56 +07:00
wrapper
c7067d9089 fix error conceal flag 2025-08-14 20:08:31 +07:00
wrapper
a3300cdb91 fix mean 2025-08-14 17:11:45 +07:00
wrapper
adbb65ac31 return code 2025-08-14 14:55:22 +07:00
wrapper
a7c4a0e42e fix sbr preset 2025-08-14 13:55:19 +07:00
wrapper
267a6b140e fix stop freq 2025-08-14 11:00:04 +07:00
wrapper
fbfc2cde3a fix vector stop freq 2025-08-14 09:58:16 +07:00
wrapper
bc4c113b68 ffmpeg patch 2025-08-13 09:23:15 +07:00
wrapper
d13979f664 patch again 2025-08-13 07:17:27 +07:00
wrapper
7faf49a81c rename 2025-08-12 22:41:51 +07:00
wrapper
bceac8a9ee flush buffers 2025-08-12 22:39:26 +07:00
wrapper
237f1a7e8f error handler 2025-08-11 19:59:52 +07:00
wrapper
480c91bc52 use specific commit 2025-08-11 17:43:17 +07:00
wrapper
821a8e169c externals done 2025-08-11 17:30:13 +07:00
wrapper
b929e62222 b 2025-08-11 16:14:01 +07:00
wrapper
dc0940ceac start no submodules 2025-08-11 16:13:45 +07:00
16 changed files with 1405 additions and 273 deletions

3
.gitignore vendored
View file

@ -42,4 +42,5 @@ _start-cmd.bat
wiki
.cache/
unused/
unused/
externals/libxaac/

3
.gitmodules vendored
View file

@ -1,3 +0,0 @@
[submodule "externals/libxaac"]
path = externals/libxaac
url = https://code.ucomsite.my.id/wrapper/libxaac

View file

@ -207,10 +207,10 @@ endif()
# Project modules
#
include(externals/externals.txt)
add_subdirectory(source)
add_subdirectory(docs)
add_subdirectory(deploy)
add_subdirectory(externals)
#
# Deployment (global project files)

View file

@ -1,17 +0,0 @@
# Always build externals as static libraries, even when libaac-next is built as shared
if (BUILD_SHARED_LIBS)
set(BUILD_SHARED_LIBS OFF)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
set_property(DIRECTORY PROPERTY EXCLUDE_FROM_ALL ON)
endif()
# Allow options shadowing with normal variables when subproject use old cmake policy
set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)
# Disable tests in all externals supporting the standard option name
set(BUILD_TESTING OFF)
# For libraries that already come with a CMakeLists file,
# simply add the directory to that file as a subdirectory
# to have CMake automatically recognize them.
add_subdirectory(libxaac)

15
externals/externals.txt vendored Normal file
View file

@ -0,0 +1,15 @@
include(ExternalProject)
ExternalProject_Add(libxaac
URL https://github.com/ittiam-systems/libxaac/archive/ae572598c3d9f4757fd743553750981c673ddfb5.zip
DOWNLOAD_EXTRACT_TIMESTAMP OFF
UPDATE_DISCONNECTED 1
CMAKE_ARGS -DCMAKE_BUILD_TYPE=Release
SOURCE_DIR "${CMAKE_SOURCE_DIR}/externals/libxaac/"
BINARY_DIR ""
INSTALL_COMMAND ""
TEST_COMMAND ""
PATCH_COMMAND patch -p1 < "${CMAKE_SOURCE_DIR}/patch/libxaac.patch"
)
ExternalProject_Get_Property(libxaac BINARY_DIR)
set(XAAC_BIN_DIR ${BINARY_DIR})

2
externals/libxaac vendored

@ -1 +1 @@
Subproject commit 80a67bda85225d6c4a1b122691004dec170c0612
Subproject commit 388435c8f8f43fe0e44bf0d31dd3965283f119ec

554
ffmpeg-git-s16only.patch Normal file
View file

@ -0,0 +1,554 @@
diff --git a/configure b/configure
index e1809a3e58..fa4fbfb1cb 100755
--- a/configure
+++ b/configure
@@ -212,6 +212,7 @@ External library support:
--enable-jni enable JNI support [no]
--enable-ladspa enable LADSPA audio filtering [no]
--enable-lcms2 enable ICC profile support via LittleCMS 2 [no]
+ --enable-libaac-next enable AAC encoding using libaac-next [no]
--enable-libaom enable AV1 video encoding/decoding via libaom [no]
--enable-libaribb24 enable ARIB text and caption decoding via libaribb24 [no]
--enable-libaribcaption enable ARIB text and caption decoding via libaribcaption [no]
@@ -1901,6 +1902,7 @@ EXTERNAL_LIBRARY_NONFREE_LIST="
EXTERNAL_LIBRARY_VERSION3_LIST="
gmp
+ libaac_next
libaribb24
liblensfun
libopencore_amrnb
@@ -3592,6 +3594,9 @@ hevc_videotoolbox_encoder_deps="pthreads"
hevc_videotoolbox_encoder_select="atsc_a53 videotoolbox_encoder"
prores_videotoolbox_encoder_deps="pthreads"
prores_videotoolbox_encoder_select="videotoolbox_encoder"
+libaac_next_decoder_deps="libaac_next"
+libaac_next_encoder_deps="libaac_next"
+libaac_next_encoder_select="audio_frame_queue"
libaom_av1_decoder_deps="libaom"
libaom_av1_encoder_deps="libaom"
libaom_av1_encoder_select="extract_extradata_bsf dovi_rpuenc"
@@ -7016,6 +7021,7 @@ enabled gnutls && require_pkg_config gnutls gnutls gnutls/gnutls.h gn
enabled jni && { [ $target_os = "android" ] && check_headers jni.h && enabled pthreads || die "ERROR: jni not found"; }
enabled ladspa && require_headers "ladspa.h dlfcn.h"
enabled lcms2 && require_pkg_config lcms2 "lcms2 >= 2.13" lcms2.h cmsCreateContext
+enabled libaac_next && require_pkg_config libaac_next "libaac >= 1.0.0" libaac.h aac_encode_open
enabled libaom && require_pkg_config libaom "aom >= 2.0.0" aom/aom_codec.h aom_codec_version
enabled liboapv && require_pkg_config liboapv "oapv >= 0.2.0.0" "oapv/oapv.h" oapve_encode
enabled libaribb24 && { check_pkg_config libaribb24 "aribb24 > 1.0.3" "aribb24/aribb24.h" arib_instance_new ||
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index fb22541f8d..740a008131 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -1144,6 +1144,8 @@ OBJS-$(CONFIG_ALAC_AT_ENCODER) += audiotoolboxenc.o
OBJS-$(CONFIG_ILBC_AT_ENCODER) += audiotoolboxenc.o
OBJS-$(CONFIG_PCM_ALAW_AT_ENCODER) += audiotoolboxenc.o
OBJS-$(CONFIG_PCM_MULAW_AT_ENCODER) += audiotoolboxenc.o
+OBJS-$(CONFIG_LIBAAC_NEXT_ENCODER) += libaac_nextenc.o
+OBJS-$(CONFIG_LIBAAC_NEXT_DECODER) += libaac_nextdec.o
OBJS-$(CONFIG_LIBAOM_AV1_DECODER) += libaomdec.o libaom.o
OBJS-$(CONFIG_LIBAOM_AV1_ENCODER) += libaomenc.o libaom.o
OBJS-$(CONFIG_LIBARIBB24_DECODER) += libaribb24.o ass.o
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index f5ec2e01e8..8fcd1a806c 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -766,6 +766,8 @@ extern const FFCodec ff_pcm_mulaw_at_encoder;
extern const FFCodec ff_pcm_mulaw_at_decoder;
extern const FFCodec ff_qdmc_at_decoder;
extern const FFCodec ff_qdm2_at_decoder;
+extern const FFCodec ff_libaac_next_encoder;
+extern const FFCodec ff_libaac_next_decoder;
extern FFCodec ff_libaom_av1_encoder;
/* preferred over libaribb24 */
extern const FFCodec ff_libaribcaption_decoder;
diff --git a/libavcodec/libaac_nextdec.c b/libavcodec/libaac_nextdec.c
new file mode 100644
index 0000000000..61345ec021
--- /dev/null
+++ b/libavcodec/libaac_nextdec.c
@@ -0,0 +1,171 @@
+/*
+ * Libaac-next decoder (libxaac based)
+ * Copyright (c) 2025 Wrapper
+ *
+ * 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
+ * Interface to libaac-next decoder.
+ */
+
+#include "avcodec.h"
+#include <libaac.h>
+#include "libavcodec/codec_id.h"
+#include "libavutil/channel_layout.h"
+#include "libavutil/error.h"
+#include "libavutil/log.h"
+#include "libavutil/opt.h"
+#include "avcodec.h"
+#include "codec_internal.h"
+#include "decode.h"
+#include "libavutil/samplefmt.h"
+#include "libavutil/mem.h"
+
+typedef struct {
+ AVClass *class;
+ AACDecode *decoder;
+ int error_conceal;
+ int esbr;
+ unsigned char *decode_buffer;
+} libaacDecodeCTX;
+
+static const AVChannelLayout aac_ch_layouts[7] = {
+ AV_CHANNEL_LAYOUT_MONO,
+ AV_CHANNEL_LAYOUT_STEREO,
+ AV_CHANNEL_LAYOUT_SURROUND,
+ AV_CHANNEL_LAYOUT_4POINT0,
+ AV_CHANNEL_LAYOUT_5POINT0_BACK,
+ AV_CHANNEL_LAYOUT_5POINT1_BACK,
+ { 0 },
+};
+
+static const AVOption aac_dec_options[] = {
+ { "conceal", "Error concealment", offsetof(libaacDecodeCTX, error_conceal), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_DECODING_PARAM },
+ { "esbr", "Enable the use of Enhanced SBR", offsetof(libaacDecodeCTX, esbr), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_DECODING_PARAM },
+ { NULL }
+};
+
+static const AVClass aac_dec_class = {
+ .class_name = "libaac",
+ .item_name = av_default_item_name,
+ .option = aac_dec_options,
+ .version = LIBAVUTIL_VERSION_INT,
+};
+
+static void aac_dec_error_handler(uint32_t errorCode, const char *section, const char *errorMsg, bool isFatal, void *handle) {
+ AVCodecContext *ctx = (AVCodecContext *)handle;
+ av_log(ctx, AV_LOG_ERROR, "%s: %s (0x%08X)\n", section, errorMsg, errorCode);
+}
+
+static av_cold int libaac_decode_init(AVCodecContext *avctx)
+{
+ libaacDecodeCTX *s = avctx->priv_data;
+ AACDecodeSettings cfg = {0};
+
+ cfg.bitsPerSamples = 16;
+ cfg.errorConceal = s->error_conceal;
+ cfg.eSBR = s->esbr;
+ cfg.frameSize = 0;
+ cfg.asc = avctx->extradata;
+ cfg.ascSize = avctx->extradata_size;
+ cfg.errorHandleCtx = avctx;
+ cfg.errorHandler = aac_dec_error_handler;
+
+ s->decoder = aac_decode_open(cfg);
+ if (!s->decoder)
+ {
+ return AVERROR(EINVAL);
+ }
+
+ s->decode_buffer = av_mallocz(4096 * 8);
+ if (!s->decode_buffer)
+ {
+ return AVERROR(ENOMEM);
+ }
+
+ avctx->sample_fmt = AV_SAMPLE_FMT_S16;
+ return 0;
+}
+
+static av_cold int libaac_decode_close(AVCodecContext *avctx)
+{
+ libaacDecodeCTX *s = avctx->priv_data;
+
+ if (s->decoder)
+ aac_decode_close(s->decoder);
+
+ return 0;
+}
+
+static int libaac_decode_frame(AVCodecContext *avctx, AVFrame *frame,
+ int *got_frame_ptr, AVPacket *avpkt)
+{
+ libaacDecodeCTX *s = avctx->priv_data;
+ uint32_t decode_size, read_size;
+ int ret;
+
+ ret = aac_decode(s->decoder, avpkt->data, avpkt->size, s->decode_buffer, &decode_size, &read_size);
+ if (ret < 0)
+ return AVERROR_EXTERNAL;
+
+ avctx->sample_rate = s->decoder->sampleRate;
+ avctx->profile = s->decoder->aot - 1;
+ avctx->ch_layout = aac_ch_layouts[s->decoder->noChannels - 1];
+ avctx->frame_size = 1024;
+
+ if (decode_size <= 0)
+ return AVERROR_EOF;
+
+ frame->nb_samples = decode_size / av_get_bytes_per_sample(avctx->sample_fmt) / avctx->ch_layout.nb_channels;
+
+ if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
+ return ret;
+
+ av_log(avctx, AV_LOG_TRACE, "aac decode size: %d, decode buf: %d\n", decode_size, avctx->ch_layout.nb_channels * frame->nb_samples * av_get_bytes_per_sample(avctx->sample_fmt));
+ memcpy(frame->data[0], s->decode_buffer, decode_size);
+
+ *got_frame_ptr = 1;
+ return read_size;
+}
+
+static av_cold void libaac_decode_flush(AVCodecContext *avctx)
+{
+ libaacDecodeCTX *s = avctx->priv_data;
+
+ if (!s->decoder)
+ return;
+
+ aac_decode_flush_buffer(s->decoder);
+}
+
+const FFCodec ff_libaac_next_decoder = {
+ .p.name = "libaac",
+ CODEC_LONG_NAME("custom libxaac-based AAC decoder"),
+ .p.type = AVMEDIA_TYPE_AUDIO,
+ .p.id = AV_CODEC_ID_AAC,
+ .priv_data_size = sizeof(libaacDecodeCTX),
+ .init = libaac_decode_init,
+ FF_CODEC_DECODE_CB(libaac_decode_frame),
+ .close = libaac_decode_close,
+ .flush = libaac_decode_flush,
+ .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF,
+ .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE,
+ .p.priv_class = &aac_dec_class,
+ .p.wrapper_name = "libaac",
+};
diff --git a/libavcodec/libaac_nextenc.c b/libavcodec/libaac_nextenc.c
new file mode 100755
index 0000000000..f9d7706285
--- /dev/null
+++ b/libavcodec/libaac_nextenc.c
@@ -0,0 +1,307 @@
+/*
+ * Libaac-next encoder (libxaac based)
+ * Copyright (c) 2025 Wrapper
+ *
+ * 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
+ * Interface to libaac-next encoder.
+ */
+
+#include <libaac.h>
+
+#include "libavutil/channel_layout.h"
+#include "libavutil/internal.h"
+#include "libavutil/intreadwrite.h"
+#include "libavutil/log.h"
+#include "libavutil/opt.h"
+#include "libavutil/mem.h"
+#include "avcodec.h"
+#include "defs.h"
+#include "audio_frame_queue.h"
+#include "codec_internal.h"
+#include "encode.h"
+#include "libavutil/samplefmt.h"
+#include "profiles.h"
+
+typedef struct
+{
+ const AVClass *class;
+ AACContext *encoder;
+ int delay_sent;
+ int flush_delay;
+
+ int eld_v2;
+ int esbr;
+ int frame_length;
+ int iq;
+ int tns;
+
+ AudioFrameQueue afq;
+} libaacEncodeCTX;
+
+static const AVOption aac_enc_options[] = {
+ { "eld_v2", "Enable ELDv2 (LD-MPS extension for ELD stereo signals)", offsetof(libaacEncodeCTX, eld_v2), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM },
+ { "esbr", "Enable the use of Enhanced SBR", offsetof(libaacEncodeCTX, esbr), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM },
+ { "frame_length", "The desired frame length", offsetof(libaacEncodeCTX, frame_length), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1024, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM },
+ { "iq", "Inverse quantization", offsetof(libaacEncodeCTX, frame_length), AV_OPT_TYPE_INT, { .i64 = 2 }, 0, 2, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM },
+ { "tns", "Temporal Noise Shaping", offsetof(libaacEncodeCTX, tns), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM },
+ FF_AAC_PROFILE_OPTS
+ { NULL }
+};
+
+static const AVClass aac_enc_class = {
+ .class_name = "libaac",
+ .item_name = av_default_item_name,
+ .option = aac_enc_options,
+ .version = LIBAVUTIL_VERSION_INT,
+};
+
+static void aac_enc_error_handler(uint32_t errorCode, const char *section, const char *errorMsg, bool isFatal, void *handle) {
+ AVCodecContext *ctx = (AVCodecContext *)handle;
+ av_log(ctx, AV_LOG_ERROR, "%s: %s (0x%08X)\n", section, errorMsg, errorCode);
+}
+
+static av_cold int libaac_encode_init(AVCodecContext *avctx)
+{
+ libaacEncodeCTX *s = avctx->priv_data;
+ AACSettings cfg = {0};
+
+ /* number of channels */
+ if (avctx->ch_layout.nb_channels < 1 || avctx->ch_layout.nb_channels > 6)
+ {
+ av_log(avctx, AV_LOG_ERROR, "encoding %d channel(s) is not allowed\n", avctx->ch_layout.nb_channels);
+ return AVERROR(EINVAL);
+ }
+
+ cfg.sampleRate = avctx->sample_rate;
+ cfg.noChannels = avctx->ch_layout.nb_channels;
+ cfg.bitsPerSamples = avctx->sample_fmt == AV_SAMPLE_FMT_FLT ? 32 : 16;
+ cfg.bitrate = avctx->bit_rate;
+ cfg.adts = !(avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER);
+ cfg.cutoff = avctx->cutoff;
+ switch (avctx->profile) {
+ case AV_PROFILE_AAC_LOW:
+ case AV_PROFILE_UNKNOWN:
+ cfg.profile = AAC_LC;
+ break;
+
+ case AV_PROFILE_AAC_HE:
+ cfg.profile = AAC_HE;
+ break;
+
+ case AV_PROFILE_AAC_HE_V2:
+ cfg.profile = AAC_HEV2;
+ break;
+
+ case AV_PROFILE_AAC_LD:
+ cfg.profile = AAC_LD;
+ break;
+
+ case AV_PROFILE_AAC_ELD:
+ cfg.profile = AAC_ELD;
+ break;
+
+ default:
+ av_log(avctx, AV_LOG_ERROR, "unsupported profile, supported profiles are LC, HE, HEv2, LD and ELD\n");
+ return AVERROR(EINVAL);
+ }
+ cfg.tns = s->tns;
+ cfg.frameSize = s->frame_length;
+ cfg.eSBR = s->esbr;
+ cfg.iq = s->iq;
+
+ cfg.errorHandleCtx = avctx;
+ cfg.errorHandler = aac_enc_error_handler;
+
+ s->encoder = aac_encode_open(cfg);
+
+ if (!s->encoder)
+ {
+ return AVERROR(EINVAL);
+ }
+
+ avctx->frame_size = s->encoder->no_samples / avctx->ch_layout.nb_channels;
+ avctx->initial_padding = s->encoder->inputDelay;
+ s->flush_delay = s->encoder->inputDelay;
+
+ av_log(avctx, AV_LOG_TRACE, "frame size: %d, initial delay: %d\n", avctx->frame_size, avctx->initial_padding);
+
+ ff_af_queue_init(avctx, &s->afq);
+
+ /* Set decoder specific info */
+ avctx->extradata_size = 0;
+ if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER)
+ {
+ avctx->extradata = av_mallocz(s->encoder->ascSize + AV_INPUT_BUFFER_PADDING_SIZE);
+
+ if (!avctx->extradata)
+ {
+ return AVERROR(ENOMEM);
+ }
+
+ avctx->extradata_size = s->encoder->ascSize;
+ memcpy(avctx->extradata, s->encoder->asc, s->encoder->ascSize);
+ }
+ return 0;
+}
+
+static int libaac_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
+ const AVFrame *frame, int *got_packet)
+{
+ libaacEncodeCTX *s = avctx->priv_data;
+ int ret;
+ int discard_padding;
+
+ if ((ret = ff_alloc_packet(avctx, pkt, s->encoder->max_out_bytes)) < 0)
+ return ret;
+
+ if (!frame)
+ {
+ av_log(avctx, AV_LOG_TRACE, "flush_delay: %d\n", s->flush_delay);
+
+ if (s->flush_delay <= 0)
+ return 0;
+
+ /* Flushing */
+ if ((ret = aac_encode(s->encoder, NULL, 0, pkt->data, (unsigned int *)&pkt->size)) < 0)
+ {
+ return AVERROR(EINVAL);
+ }
+
+ s->flush_delay -= avctx->frame_size;
+ }
+ else
+ {
+ /* Encoding */
+ if ((ret = ff_af_queue_add(&s->afq, frame)) < 0)
+ return ret;
+
+ int encodeSize = av_get_bytes_per_sample(avctx->sample_fmt) * avctx->ch_layout.nb_channels * frame->nb_samples;
+ av_log(avctx, AV_LOG_TRACE, "encode size: %d\n", encodeSize);
+
+ if ((ret = aac_encode(s->encoder, frame->data[0], encodeSize, pkt->data, (unsigned int *)&pkt->size)) < 0)
+ {
+ return AVERROR(EINVAL);
+ }
+ }
+
+ ff_af_queue_remove(&s->afq, avctx->frame_size, &pkt->pts, &pkt->duration);
+
+ /* discard padding copied from fdkaac encoder */
+ discard_padding = avctx->frame_size - pkt->duration;
+
+ // Check if subtraction resulted in an overflow
+ if ((discard_padding < avctx->frame_size) != (pkt->duration > 0))
+ {
+ av_log(avctx, AV_LOG_ERROR, "discard padding overflow\n");
+ return AVERROR(EINVAL);
+ }
+
+ if ((!s->delay_sent && avctx->initial_padding > 0) || discard_padding > 0)
+ {
+ uint8_t *side_data =
+ av_packet_new_side_data(pkt, AV_PKT_DATA_SKIP_SAMPLES, 10);
+ if (!side_data)
+ return AVERROR(ENOMEM);
+ if (!s->delay_sent)
+ {
+ AV_WL32(side_data, avctx->initial_padding);
+ s->delay_sent = 1;
+ }
+ AV_WL32(side_data + 4, discard_padding);
+ }
+
+ pkt->flags |= AV_PKT_FLAG_KEY;
+ *got_packet = 1;
+ return 0;
+}
+
+static void libaac_encode_flush(AVCodecContext *avctx)
+{
+ libaacEncodeCTX *s = avctx->priv_data;
+ uint8_t sink_null[32768];
+ int64_t pts, duration;
+ uint32_t out_bytes;
+
+ av_log(avctx, AV_LOG_TRACE, "encoder flush\n");
+ ff_af_queue_remove(&s->afq, s->afq.frame_count, &pts, &duration);
+ aac_encode(s->encoder, NULL, 0, sink_null, &out_bytes);
+}
+
+static av_cold int libaac_encode_close(AVCodecContext *avctx)
+{
+ libaacEncodeCTX *s = avctx->priv_data;
+
+ if (s->encoder)
+ aac_encode_close(s->encoder);
+
+ ff_af_queue_close(&s->afq);
+
+ return 0;
+}
+
+static const FFCodecDefault defaults[] = {
+ {"b", "128000"},
+ {NULL}};
+
+static const AVProfile libaac_profiles[] = {
+ { AV_PROFILE_AAC_LOW, "LC" },
+ { AV_PROFILE_AAC_HE, "HE-AAC" },
+ { AV_PROFILE_AAC_HE_V2, "HE-AACv2" },
+ { AV_PROFILE_AAC_LD, "LD" },
+ { AV_PROFILE_AAC_ELD, "ELD" },
+ {AV_PROFILE_UNKNOWN},
+};
+
+static const int aac_sample_rates[] = {
+ 96000, 88200, 64000, 48000, 44100, 32000,
+ 24000, 22050, 16000, 12000, 11025, 8000, 0
+};
+
+static const AVChannelLayout aac_ch_layouts[7] = {
+ AV_CHANNEL_LAYOUT_MONO,
+ AV_CHANNEL_LAYOUT_STEREO,
+ AV_CHANNEL_LAYOUT_SURROUND,
+ AV_CHANNEL_LAYOUT_4POINT0,
+ AV_CHANNEL_LAYOUT_5POINT0_BACK,
+ AV_CHANNEL_LAYOUT_5POINT1_BACK,
+ { 0 },
+};
+
+const FFCodec ff_libaac_next_encoder = {
+ .p.name = "libaac",
+ CODEC_LONG_NAME("custom libxaac-based AAC encoder"),
+ .p.type = AVMEDIA_TYPE_AUDIO,
+ .p.id = AV_CODEC_ID_AAC,
+ .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_ENCODER_FLUSH,
+ .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE,
+ .priv_data_size = sizeof(libaacEncodeCTX),
+ .init = libaac_encode_init,
+ FF_CODEC_ENCODE_CB(libaac_encode_frame),
+ .flush = libaac_encode_flush,
+ .close = libaac_encode_close,
+ CODEC_SAMPLEFMTS(AV_SAMPLE_FMT_S16),
+ .p.priv_class = &aac_enc_class,
+ .defaults = defaults,
+ .p.profiles = libaac_profiles,
+ CODEC_SAMPLERATES_ARRAY(aac_sample_rates),
+ .p.wrapper_name = "libaac",
+ CODEC_CH_LAYOUTS_ARRAY(aac_ch_layouts),
+};

554
ffmpeg-git.patch Normal file
View file

@ -0,0 +1,554 @@
diff --git a/configure b/configure
index e1809a3e58..fa4fbfb1cb 100755
--- a/configure
+++ b/configure
@@ -212,6 +212,7 @@ External library support:
--enable-jni enable JNI support [no]
--enable-ladspa enable LADSPA audio filtering [no]
--enable-lcms2 enable ICC profile support via LittleCMS 2 [no]
+ --enable-libaac-next enable AAC encoding using libaac-next [no]
--enable-libaom enable AV1 video encoding/decoding via libaom [no]
--enable-libaribb24 enable ARIB text and caption decoding via libaribb24 [no]
--enable-libaribcaption enable ARIB text and caption decoding via libaribcaption [no]
@@ -1901,6 +1902,7 @@ EXTERNAL_LIBRARY_NONFREE_LIST="
EXTERNAL_LIBRARY_VERSION3_LIST="
gmp
+ libaac_next
libaribb24
liblensfun
libopencore_amrnb
@@ -3592,6 +3594,9 @@ hevc_videotoolbox_encoder_deps="pthreads"
hevc_videotoolbox_encoder_select="atsc_a53 videotoolbox_encoder"
prores_videotoolbox_encoder_deps="pthreads"
prores_videotoolbox_encoder_select="videotoolbox_encoder"
+libaac_next_decoder_deps="libaac_next"
+libaac_next_encoder_deps="libaac_next"
+libaac_next_encoder_select="audio_frame_queue"
libaom_av1_decoder_deps="libaom"
libaom_av1_encoder_deps="libaom"
libaom_av1_encoder_select="extract_extradata_bsf dovi_rpuenc"
@@ -7016,6 +7021,7 @@ enabled gnutls && require_pkg_config gnutls gnutls gnutls/gnutls.h gn
enabled jni && { [ $target_os = "android" ] && check_headers jni.h && enabled pthreads || die "ERROR: jni not found"; }
enabled ladspa && require_headers "ladspa.h dlfcn.h"
enabled lcms2 && require_pkg_config lcms2 "lcms2 >= 2.13" lcms2.h cmsCreateContext
+enabled libaac_next && require_pkg_config libaac_next "libaac >= 1.0.0" libaac.h aac_encode_open
enabled libaom && require_pkg_config libaom "aom >= 2.0.0" aom/aom_codec.h aom_codec_version
enabled liboapv && require_pkg_config liboapv "oapv >= 0.2.0.0" "oapv/oapv.h" oapve_encode
enabled libaribb24 && { check_pkg_config libaribb24 "aribb24 > 1.0.3" "aribb24/aribb24.h" arib_instance_new ||
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index fb22541f8d..740a008131 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -1144,6 +1144,8 @@ OBJS-$(CONFIG_ALAC_AT_ENCODER) += audiotoolboxenc.o
OBJS-$(CONFIG_ILBC_AT_ENCODER) += audiotoolboxenc.o
OBJS-$(CONFIG_PCM_ALAW_AT_ENCODER) += audiotoolboxenc.o
OBJS-$(CONFIG_PCM_MULAW_AT_ENCODER) += audiotoolboxenc.o
+OBJS-$(CONFIG_LIBAAC_NEXT_ENCODER) += libaac_nextenc.o
+OBJS-$(CONFIG_LIBAAC_NEXT_DECODER) += libaac_nextdec.o
OBJS-$(CONFIG_LIBAOM_AV1_DECODER) += libaomdec.o libaom.o
OBJS-$(CONFIG_LIBAOM_AV1_ENCODER) += libaomenc.o libaom.o
OBJS-$(CONFIG_LIBARIBB24_DECODER) += libaribb24.o ass.o
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index f5ec2e01e8..8fcd1a806c 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -766,6 +766,8 @@ extern const FFCodec ff_pcm_mulaw_at_encoder;
extern const FFCodec ff_pcm_mulaw_at_decoder;
extern const FFCodec ff_qdmc_at_decoder;
extern const FFCodec ff_qdm2_at_decoder;
+extern const FFCodec ff_libaac_next_encoder;
+extern const FFCodec ff_libaac_next_decoder;
extern FFCodec ff_libaom_av1_encoder;
/* preferred over libaribb24 */
extern const FFCodec ff_libaribcaption_decoder;
diff --git a/libavcodec/libaac_nextdec.c b/libavcodec/libaac_nextdec.c
new file mode 100644
index 0000000000..61345ec021
--- /dev/null
+++ b/libavcodec/libaac_nextdec.c
@@ -0,0 +1,171 @@
+/*
+ * Libaac-next decoder (libxaac based)
+ * Copyright (c) 2025 Wrapper
+ *
+ * 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
+ * Interface to libaac-next decoder.
+ */
+
+#include "avcodec.h"
+#include <libaac.h>
+#include "libavcodec/codec_id.h"
+#include "libavutil/channel_layout.h"
+#include "libavutil/error.h"
+#include "libavutil/log.h"
+#include "libavutil/opt.h"
+#include "avcodec.h"
+#include "codec_internal.h"
+#include "decode.h"
+#include "libavutil/samplefmt.h"
+#include "libavutil/mem.h"
+
+typedef struct {
+ AVClass *class;
+ AACDecode *decoder;
+ int error_conceal;
+ int esbr;
+ unsigned char *decode_buffer;
+} libaacDecodeCTX;
+
+static const AVChannelLayout aac_ch_layouts[7] = {
+ AV_CHANNEL_LAYOUT_MONO,
+ AV_CHANNEL_LAYOUT_STEREO,
+ AV_CHANNEL_LAYOUT_SURROUND,
+ AV_CHANNEL_LAYOUT_4POINT0,
+ AV_CHANNEL_LAYOUT_5POINT0_BACK,
+ AV_CHANNEL_LAYOUT_5POINT1_BACK,
+ { 0 },
+};
+
+static const AVOption aac_dec_options[] = {
+ { "conceal", "Error concealment", offsetof(libaacDecodeCTX, error_conceal), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_DECODING_PARAM },
+ { "esbr", "Enable the use of Enhanced SBR", offsetof(libaacDecodeCTX, esbr), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_DECODING_PARAM },
+ { NULL }
+};
+
+static const AVClass aac_dec_class = {
+ .class_name = "libaac",
+ .item_name = av_default_item_name,
+ .option = aac_dec_options,
+ .version = LIBAVUTIL_VERSION_INT,
+};
+
+static void aac_dec_error_handler(uint32_t errorCode, const char *section, const char *errorMsg, bool isFatal, void *handle) {
+ AVCodecContext *ctx = (AVCodecContext *)handle;
+ av_log(ctx, AV_LOG_ERROR, "%s: %s (0x%08X)\n", section, errorMsg, errorCode);
+}
+
+static av_cold int libaac_decode_init(AVCodecContext *avctx)
+{
+ libaacDecodeCTX *s = avctx->priv_data;
+ AACDecodeSettings cfg = {0};
+
+ cfg.bitsPerSamples = 16;
+ cfg.errorConceal = s->error_conceal;
+ cfg.eSBR = s->esbr;
+ cfg.frameSize = 0;
+ cfg.asc = avctx->extradata;
+ cfg.ascSize = avctx->extradata_size;
+ cfg.errorHandleCtx = avctx;
+ cfg.errorHandler = aac_dec_error_handler;
+
+ s->decoder = aac_decode_open(cfg);
+ if (!s->decoder)
+ {
+ return AVERROR(EINVAL);
+ }
+
+ s->decode_buffer = av_mallocz(4096 * 8);
+ if (!s->decode_buffer)
+ {
+ return AVERROR(ENOMEM);
+ }
+
+ avctx->sample_fmt = AV_SAMPLE_FMT_S16;
+ return 0;
+}
+
+static av_cold int libaac_decode_close(AVCodecContext *avctx)
+{
+ libaacDecodeCTX *s = avctx->priv_data;
+
+ if (s->decoder)
+ aac_decode_close(s->decoder);
+
+ return 0;
+}
+
+static int libaac_decode_frame(AVCodecContext *avctx, AVFrame *frame,
+ int *got_frame_ptr, AVPacket *avpkt)
+{
+ libaacDecodeCTX *s = avctx->priv_data;
+ uint32_t decode_size, read_size;
+ int ret;
+
+ ret = aac_decode(s->decoder, avpkt->data, avpkt->size, s->decode_buffer, &decode_size, &read_size);
+ if (ret < 0)
+ return AVERROR_EXTERNAL;
+
+ avctx->sample_rate = s->decoder->sampleRate;
+ avctx->profile = s->decoder->aot - 1;
+ avctx->ch_layout = aac_ch_layouts[s->decoder->noChannels - 1];
+ avctx->frame_size = 1024;
+
+ if (decode_size <= 0)
+ return AVERROR_EOF;
+
+ frame->nb_samples = decode_size / av_get_bytes_per_sample(avctx->sample_fmt) / avctx->ch_layout.nb_channels;
+
+ if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
+ return ret;
+
+ av_log(avctx, AV_LOG_TRACE, "aac decode size: %d, decode buf: %d\n", decode_size, avctx->ch_layout.nb_channels * frame->nb_samples * av_get_bytes_per_sample(avctx->sample_fmt));
+ memcpy(frame->data[0], s->decode_buffer, decode_size);
+
+ *got_frame_ptr = 1;
+ return read_size;
+}
+
+static av_cold void libaac_decode_flush(AVCodecContext *avctx)
+{
+ libaacDecodeCTX *s = avctx->priv_data;
+
+ if (!s->decoder)
+ return;
+
+ aac_decode_flush_buffer(s->decoder);
+}
+
+const FFCodec ff_libaac_next_decoder = {
+ .p.name = "libaac",
+ CODEC_LONG_NAME("custom libxaac-based AAC decoder"),
+ .p.type = AVMEDIA_TYPE_AUDIO,
+ .p.id = AV_CODEC_ID_AAC,
+ .priv_data_size = sizeof(libaacDecodeCTX),
+ .init = libaac_decode_init,
+ FF_CODEC_DECODE_CB(libaac_decode_frame),
+ .close = libaac_decode_close,
+ .flush = libaac_decode_flush,
+ .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF,
+ .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE,
+ .p.priv_class = &aac_dec_class,
+ .p.wrapper_name = "libaac",
+};
diff --git a/libavcodec/libaac_nextenc.c b/libavcodec/libaac_nextenc.c
new file mode 100755
index 0000000000..f9d7706285
--- /dev/null
+++ b/libavcodec/libaac_nextenc.c
@@ -0,0 +1,307 @@
+/*
+ * Libaac-next encoder (libxaac based)
+ * Copyright (c) 2025 Wrapper
+ *
+ * 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
+ * Interface to libaac-next encoder.
+ */
+
+#include <libaac.h>
+
+#include "libavutil/channel_layout.h"
+#include "libavutil/internal.h"
+#include "libavutil/intreadwrite.h"
+#include "libavutil/log.h"
+#include "libavutil/opt.h"
+#include "libavutil/mem.h"
+#include "avcodec.h"
+#include "defs.h"
+#include "audio_frame_queue.h"
+#include "codec_internal.h"
+#include "encode.h"
+#include "libavutil/samplefmt.h"
+#include "profiles.h"
+
+typedef struct
+{
+ const AVClass *class;
+ AACContext *encoder;
+ int delay_sent;
+ int flush_delay;
+
+ int eld_v2;
+ int esbr;
+ int frame_length;
+ int iq;
+ int tns;
+
+ AudioFrameQueue afq;
+} libaacEncodeCTX;
+
+static const AVOption aac_enc_options[] = {
+ { "eld_v2", "Enable ELDv2 (LD-MPS extension for ELD stereo signals)", offsetof(libaacEncodeCTX, eld_v2), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM },
+ { "esbr", "Enable the use of Enhanced SBR", offsetof(libaacEncodeCTX, esbr), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM },
+ { "frame_length", "The desired frame length", offsetof(libaacEncodeCTX, frame_length), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1024, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM },
+ { "iq", "Inverse quantization", offsetof(libaacEncodeCTX, frame_length), AV_OPT_TYPE_INT, { .i64 = 2 }, 0, 2, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM },
+ { "tns", "Temporal Noise Shaping", offsetof(libaacEncodeCTX, tns), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM },
+ FF_AAC_PROFILE_OPTS
+ { NULL }
+};
+
+static const AVClass aac_enc_class = {
+ .class_name = "libaac",
+ .item_name = av_default_item_name,
+ .option = aac_enc_options,
+ .version = LIBAVUTIL_VERSION_INT,
+};
+
+static void aac_enc_error_handler(uint32_t errorCode, const char *section, const char *errorMsg, bool isFatal, void *handle) {
+ AVCodecContext *ctx = (AVCodecContext *)handle;
+ av_log(ctx, AV_LOG_ERROR, "%s: %s (0x%08X)\n", section, errorMsg, errorCode);
+}
+
+static av_cold int libaac_encode_init(AVCodecContext *avctx)
+{
+ libaacEncodeCTX *s = avctx->priv_data;
+ AACSettings cfg = {0};
+
+ /* number of channels */
+ if (avctx->ch_layout.nb_channels < 1 || avctx->ch_layout.nb_channels > 6)
+ {
+ av_log(avctx, AV_LOG_ERROR, "encoding %d channel(s) is not allowed\n", avctx->ch_layout.nb_channels);
+ return AVERROR(EINVAL);
+ }
+
+ cfg.sampleRate = avctx->sample_rate;
+ cfg.noChannels = avctx->ch_layout.nb_channels;
+ cfg.bitsPerSamples = avctx->sample_fmt == AV_SAMPLE_FMT_FLT ? 32 : 16;
+ cfg.bitrate = avctx->bit_rate;
+ cfg.adts = !(avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER);
+ cfg.cutoff = avctx->cutoff;
+ switch (avctx->profile) {
+ case AV_PROFILE_AAC_LOW:
+ case AV_PROFILE_UNKNOWN:
+ cfg.profile = AAC_LC;
+ break;
+
+ case AV_PROFILE_AAC_HE:
+ cfg.profile = AAC_HE;
+ break;
+
+ case AV_PROFILE_AAC_HE_V2:
+ cfg.profile = AAC_HEV2;
+ break;
+
+ case AV_PROFILE_AAC_LD:
+ cfg.profile = AAC_LD;
+ break;
+
+ case AV_PROFILE_AAC_ELD:
+ cfg.profile = AAC_ELD;
+ break;
+
+ default:
+ av_log(avctx, AV_LOG_ERROR, "unsupported profile, supported profiles are LC, HE, HEv2, LD and ELD\n");
+ return AVERROR(EINVAL);
+ }
+ cfg.tns = s->tns;
+ cfg.frameSize = s->frame_length;
+ cfg.eSBR = s->esbr;
+ cfg.iq = s->iq;
+
+ cfg.errorHandleCtx = avctx;
+ cfg.errorHandler = aac_enc_error_handler;
+
+ s->encoder = aac_encode_open(cfg);
+
+ if (!s->encoder)
+ {
+ return AVERROR(EINVAL);
+ }
+
+ avctx->frame_size = s->encoder->no_samples / avctx->ch_layout.nb_channels;
+ avctx->initial_padding = s->encoder->inputDelay;
+ s->flush_delay = s->encoder->inputDelay;
+
+ av_log(avctx, AV_LOG_TRACE, "frame size: %d, initial delay: %d\n", avctx->frame_size, avctx->initial_padding);
+
+ ff_af_queue_init(avctx, &s->afq);
+
+ /* Set decoder specific info */
+ avctx->extradata_size = 0;
+ if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER)
+ {
+ avctx->extradata = av_mallocz(s->encoder->ascSize + AV_INPUT_BUFFER_PADDING_SIZE);
+
+ if (!avctx->extradata)
+ {
+ return AVERROR(ENOMEM);
+ }
+
+ avctx->extradata_size = s->encoder->ascSize;
+ memcpy(avctx->extradata, s->encoder->asc, s->encoder->ascSize);
+ }
+ return 0;
+}
+
+static int libaac_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
+ const AVFrame *frame, int *got_packet)
+{
+ libaacEncodeCTX *s = avctx->priv_data;
+ int ret;
+ int discard_padding;
+
+ if ((ret = ff_alloc_packet(avctx, pkt, s->encoder->max_out_bytes)) < 0)
+ return ret;
+
+ if (!frame)
+ {
+ av_log(avctx, AV_LOG_TRACE, "flush_delay: %d\n", s->flush_delay);
+
+ if (s->flush_delay <= 0)
+ return 0;
+
+ /* Flushing */
+ if ((ret = aac_encode(s->encoder, NULL, 0, pkt->data, (unsigned int *)&pkt->size)) < 0)
+ {
+ return AVERROR(EINVAL);
+ }
+
+ s->flush_delay -= avctx->frame_size;
+ }
+ else
+ {
+ /* Encoding */
+ if ((ret = ff_af_queue_add(&s->afq, frame)) < 0)
+ return ret;
+
+ int encodeSize = av_get_bytes_per_sample(avctx->sample_fmt) * avctx->ch_layout.nb_channels * frame->nb_samples;
+ av_log(avctx, AV_LOG_TRACE, "encode size: %d\n", encodeSize);
+
+ if ((ret = aac_encode(s->encoder, frame->data[0], encodeSize, pkt->data, (unsigned int *)&pkt->size)) < 0)
+ {
+ return AVERROR(EINVAL);
+ }
+ }
+
+ ff_af_queue_remove(&s->afq, avctx->frame_size, &pkt->pts, &pkt->duration);
+
+ /* discard padding copied from fdkaac encoder */
+ discard_padding = avctx->frame_size - pkt->duration;
+
+ // Check if subtraction resulted in an overflow
+ if ((discard_padding < avctx->frame_size) != (pkt->duration > 0))
+ {
+ av_log(avctx, AV_LOG_ERROR, "discard padding overflow\n");
+ return AVERROR(EINVAL);
+ }
+
+ if ((!s->delay_sent && avctx->initial_padding > 0) || discard_padding > 0)
+ {
+ uint8_t *side_data =
+ av_packet_new_side_data(pkt, AV_PKT_DATA_SKIP_SAMPLES, 10);
+ if (!side_data)
+ return AVERROR(ENOMEM);
+ if (!s->delay_sent)
+ {
+ AV_WL32(side_data, avctx->initial_padding);
+ s->delay_sent = 1;
+ }
+ AV_WL32(side_data + 4, discard_padding);
+ }
+
+ pkt->flags |= AV_PKT_FLAG_KEY;
+ *got_packet = 1;
+ return 0;
+}
+
+static void libaac_encode_flush(AVCodecContext *avctx)
+{
+ libaacEncodeCTX *s = avctx->priv_data;
+ uint8_t sink_null[32768];
+ int64_t pts, duration;
+ uint32_t out_bytes;
+
+ av_log(avctx, AV_LOG_TRACE, "encoder flush\n");
+ ff_af_queue_remove(&s->afq, s->afq.frame_count, &pts, &duration);
+ aac_encode(s->encoder, NULL, 0, sink_null, &out_bytes);
+}
+
+static av_cold int libaac_encode_close(AVCodecContext *avctx)
+{
+ libaacEncodeCTX *s = avctx->priv_data;
+
+ if (s->encoder)
+ aac_encode_close(s->encoder);
+
+ ff_af_queue_close(&s->afq);
+
+ return 0;
+}
+
+static const FFCodecDefault defaults[] = {
+ {"b", "128000"},
+ {NULL}};
+
+static const AVProfile libaac_profiles[] = {
+ { AV_PROFILE_AAC_LOW, "LC" },
+ { AV_PROFILE_AAC_HE, "HE-AAC" },
+ { AV_PROFILE_AAC_HE_V2, "HE-AACv2" },
+ { AV_PROFILE_AAC_LD, "LD" },
+ { AV_PROFILE_AAC_ELD, "ELD" },
+ {AV_PROFILE_UNKNOWN},
+};
+
+static const int aac_sample_rates[] = {
+ 96000, 88200, 64000, 48000, 44100, 32000,
+ 24000, 22050, 16000, 12000, 11025, 8000, 0
+};
+
+static const AVChannelLayout aac_ch_layouts[7] = {
+ AV_CHANNEL_LAYOUT_MONO,
+ AV_CHANNEL_LAYOUT_STEREO,
+ AV_CHANNEL_LAYOUT_SURROUND,
+ AV_CHANNEL_LAYOUT_4POINT0,
+ AV_CHANNEL_LAYOUT_5POINT0_BACK,
+ AV_CHANNEL_LAYOUT_5POINT1_BACK,
+ { 0 },
+};
+
+const FFCodec ff_libaac_next_encoder = {
+ .p.name = "libaac",
+ CODEC_LONG_NAME("custom libxaac-based AAC encoder"),
+ .p.type = AVMEDIA_TYPE_AUDIO,
+ .p.id = AV_CODEC_ID_AAC,
+ .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_ENCODER_FLUSH,
+ .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE,
+ .priv_data_size = sizeof(libaacEncodeCTX),
+ .init = libaac_encode_init,
+ FF_CODEC_ENCODE_CB(libaac_encode_frame),
+ .flush = libaac_encode_flush,
+ .close = libaac_encode_close,
+ CODEC_SAMPLEFMTS(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S16),
+ .p.priv_class = &aac_enc_class,
+ .defaults = defaults,
+ .p.profiles = libaac_profiles,
+ CODEC_SAMPLERATES_ARRAY(aac_sample_rates),
+ .p.wrapper_name = "libaac",
+ CODEC_CH_LAYOUTS_ARRAY(aac_ch_layouts),
+};

View file

@ -1,3 +1,13 @@
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 82539b7..4996c67 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -27,3 +27,5 @@ include("${XAAC_ROOT}/encoder/libxaacenc.cmake")
include("${XAAC_ROOT}/test/encoder/xaacenc.cmake")
include("${XAAC_ROOT}/fuzzer/xaac_enc_fuzzer.cmake")
+set_property(TARGET libxaacenc PROPERTY POSITION_INDEPENDENT_CODE 1)
+set_property(TARGET libxaacdec PROPERTY POSITION_INDEPENDENT_CODE 1)
diff --git a/cmake/utils.cmake b/cmake/utils.cmake
index 5d9cd37..3196501 100644
--- a/cmake/utils.cmake
@ -11,7 +21,7 @@ index 5d9cd37..3196501 100644
# Adds libraries needed for executables
diff --git a/decoder/ixheaacd_api.c b/decoder/ixheaacd_api.c
index 5e6a0ac..c4ae8e0 100644
index 5e6a0ac..3504a10 100644
--- a/decoder/ixheaacd_api.c
+++ b/decoder/ixheaacd_api.c
@@ -579,7 +579,7 @@ IA_ERRORCODE ixheaacd_dec_api(pVOID p_ia_xheaac_dec_obj, WORD32 i_cmd,
@ -23,6 +33,23 @@ index 5e6a0ac..c4ae8e0 100644
p_obj_exhaacplus_dec->aac_config.ui_pcm_wdsz = 16;
return (IA_XHEAAC_DEC_CONFIG_NONFATAL_INVALID_PCM_WDSZ);
}
@@ -940,6 +940,7 @@ IA_ERRORCODE ixheaacd_dec_api(pVOID p_ia_xheaac_dec_obj, WORD32 i_cmd,
} else {
*pui_value = p_obj_exhaacplus_dec->p_state_aac->audio_object_type;
}
+ if (*pui_value == AOT_AAC_LC) *pui_value = p_obj_exhaacplus_dec->p_state_aac->init_sbr_flag ? (p_obj_exhaacplus_dec->p_state_aac->init_ps_flag ? AOT_PS : AOT_SBR) : AOT_AAC_LC;
} else {
*pui_value = AOT_AAC_LC;
}
@@ -2530,6 +2531,8 @@ IA_ERRORCODE ixheaacd_dec_init(
p_obj_exhaacplus_dec->aac_config.ui_n_channels = num_channels_1;
p_obj_exhaacplus_dec->aac_config.ui_samp_freq = sample_rate;
p_state_enhaacplus_dec->ui_init_done = 1;
+ p_state_enhaacplus_dec->init_sbr_flag = sbr_present_flag;
+ p_state_enhaacplus_dec->init_ps_flag = !p_obj_exhaacplus_dec->aac_config.ui_channel_mode;
memcpy(it_bit_buff, &temp_bit_buff, sizeof(struct ia_bit_buf_struct));
diff --git a/decoder/ixheaacd_decode_main.c b/decoder/ixheaacd_decode_main.c
index 982a6aa..d827687 100644
--- a/decoder/ixheaacd_decode_main.c
@ -56,8 +83,21 @@ index 982a6aa..d827687 100644
} else {
WORD8 *out_24bit = (WORD8 *)out_buf;
for (i = 0; i < num; i++) {
diff --git a/decoder/ixheaacd_struct_def.h b/decoder/ixheaacd_struct_def.h
index fea3b56..8518407 100644
--- a/decoder/ixheaacd_struct_def.h
+++ b/decoder/ixheaacd_struct_def.h
@@ -162,6 +162,8 @@ typedef struct ia_aac_dec_state_struct {
UWORD32 ui_input_over;
UWORD32 header_dec_done;
WORD32 frame_counter;
+ WORD32 init_sbr_flag;
+ WORD32 init_ps_flag;
ia_aac_decoder_struct *pstr_aac_dec_info[MAX_BS_ELEMENT];
UWORD32 ch_config;
diff --git a/encoder/ixheaace_api.c b/encoder/ixheaace_api.c
index 6d5c47e..22fe7e4 100644
index 6d5c47e..749cac6 100644
--- a/encoder/ixheaace_api.c
+++ b/encoder/ixheaace_api.c
@@ -831,7 +831,7 @@ static IA_ERRORCODE ixheaace_set_config_params(ixheaace_api_struct *pstr_api_str
@ -89,11 +129,20 @@ index 6d5c47e..22fe7e4 100644
}
pstr_api_struct->config[0].aac_config.full_bandwidth =
pstr_input_config->aac_config.full_bandwidth;
+ pstr_api_struct->config[0].aac_config.band_width =
+ pstr_api_struct->config[0].aac_config.band_width =
+ pstr_input_config->aac_config.bandwidth;
}
return IA_NO_ERROR;
@@ -2474,7 +2478,7 @@ static IA_ERRORCODE ia_enhaacplus_enc_init(ixheaace_api_struct *pstr_api_struct,
pstr_aac_config->bit_rate,
(pstr_api_struct->pstr_state->mps_enable
? 1
- : pstr_api_struct->config[ele_idx].chmode_nchannels),
+ : pstr_aac_config->num_out_channels),
pstr_aac_config->sample_rate, &core_sample_rate,
pstr_api_struct->spectral_band_replication_tabs.ptr_qmf_tab,
pstr_api_struct->pstr_state->aot)) {
@@ -2692,6 +2696,7 @@ static IA_ERRORCODE ia_enhaacplus_enc_execute(ixheaace_api_struct *pstr_api_stru
iexheaac_encoder_str **pstr_aac_enc;
iaace_config *pstr_aac_config;
@ -315,143 +364,49 @@ index eb9e882..e85b300 100644
const FLOAT32 tns_coeff_3_borders[8];
const FLOAT32 tns_coeff_4[16];
diff --git a/encoder/ixheaace_sbr_freq_scaling.c b/encoder/ixheaace_sbr_freq_scaling.c
index 7eec5a9..192907e 100644
index 7eec5a9..1f08fbd 100644
--- a/encoder/ixheaace_sbr_freq_scaling.c
+++ b/encoder/ixheaace_sbr_freq_scaling.c
@@ -158,31 +158,31 @@ static WORD32 ixheaace_get_start_freq(WORD32 fs, WORD32 start_freq) {
WORD32 minimum_k0;
@@ -231,16 +231,16 @@ static WORD32 ixheaace_get_stop_freq(WORD32 fs, WORD32 stop_freq) {
switch (fs) {
- case 16000:
+ case 8000:
minimum_k0 = 24;
case 16000:
- k1_min = ixheaace_stop_freq_16k[0];
- v_stop_freq = (WORD32 *)&ixheaace_stop_freq_16k[0];
+ k1_min = ixheaace_usac_stop_freq_16k[0];
+ v_stop_freq = (WORD32 *)&ixheaace_usac_stop_freq_16k[0];
break;
- case 22050:
+ case 11025:
minimum_k0 = 17;
case 22050:
- k1_min = ixheaace_stop_freq_22k[0];
- v_stop_freq = (WORD32 *)&ixheaace_stop_freq_22k[0];
+ k1_min = ixheaace_usac_stop_freq_22k[0];
+ v_stop_freq = (WORD32 *)&ixheaace_usac_stop_freq_22k[0];
break;
- case 24000:
+ case 12000:
minimum_k0 = 16;
case 24000:
- k1_min = ixheaace_stop_freq_24k[0];
- v_stop_freq = (WORD32 *)&ixheaace_stop_freq_24k[0];
+ k1_min = ixheaace_usac_stop_freq_24k[0];
+ v_stop_freq = (WORD32 *)&ixheaace_usac_stop_freq_24k[0];
break;
- case 32000:
+ case 16000:
minimum_k0 = 16;
break;
- case 44100:
+ case 22050:
minimum_k0 = 12;
break;
- case 48000:
+ case 24000:
minimum_k0 = 11;
break;
- case 64000:
+ case 32000:
minimum_k0 = 10;
break;
- case 88200:
+ case 44100:
minimum_k0 = 7;
break;
- case 96000:
+ case 48000:
minimum_k0 = 7;
break;
default:
@@ -190,30 +190,30 @@ static WORD32 ixheaace_get_start_freq(WORD32 fs, WORD32 start_freq) {
}
switch (fs) {
- case 16000: {
+ case 8000: {
return (minimum_k0 + vector_offset_16k[start_freq]);
} break;
- case 22050: {
+ case 11025: {
return (minimum_k0 + vector_offset_22k[start_freq]);
} break;
- case 24000: {
+ case 12000: {
return (minimum_k0 + vector_offset_24k[start_freq]);
} break;
- case 32000: {
+ case 16000: {
return (minimum_k0 + vector_offset_32k[start_freq]);
} break;
- case 44100:
- case 48000:
- case 64000: {
+ case 22050:
+ case 24000:
+ case 32000: {
return (minimum_k0 + vector_offset_44_48_64[start_freq]);
} break;
- case 88200:
- case 96000: {
+ case 44100:
+ case 48000: {
return (minimum_k0 + vector_offset_88_96[start_freq]);
} break;
@@ -230,36 +230,54 @@ static WORD32 ixheaace_get_stop_freq(WORD32 fs, WORD32 stop_freq) {
WORD32 v_dstop[13];
switch (fs) {
- case 16000:
+ case 8000:
k1_min = ixheaace_stop_freq_16k[0];
v_stop_freq = (WORD32 *)&ixheaace_stop_freq_16k[0];
break;
- case 22050:
+ case 11025:
k1_min = ixheaace_stop_freq_22k[0];
v_stop_freq = (WORD32 *)&ixheaace_stop_freq_22k[0];
break;
- case 24000:
+ case 12000:
k1_min = ixheaace_stop_freq_24k[0];
v_stop_freq = (WORD32 *)&ixheaace_stop_freq_24k[0];
break;
- case 32000:
+ case 16000:
case 32000:
k1_min = 32;
v_stop_freq = (WORD32 *)vector_stop_freq_32;
break;
- case 44100:
+ case 22050:
k1_min = 23;
v_stop_freq = (WORD32 *)vector_stop_freq_44;
break;
- case 48000:
+ case 24000:
k1_min = 21;
@@ -260,6 +260,24 @@ static WORD32 ixheaace_get_stop_freq(WORD32 fs, WORD32 stop_freq) {
v_stop_freq = (WORD32 *)vector_stop_freq_48;
break;
+ case 32000:
+ case 64000:
+ k1_min = 20;
+
+ v_stop_freq = (WORD32 *)vector_stop_freq_64;
+ break;
+
+ case 44100:
+ case 88200:
+ k1_min = 15;
+
+ v_stop_freq = (WORD32 *)vector_stop_freq_88;
+ break;
+
+ case 48000:
+ case 96000:
+ k1_min = 13;
+
+ v_stop_freq = (WORD32 *)vector_stop_freq_96;
@ -461,7 +416,7 @@ index 7eec5a9..192907e 100644
v_stop_freq = (WORD32 *)vector_stop_freq_32;
k1_min = 21; /* illegal fs */
diff --git a/encoder/ixheaace_sbr_main.c b/encoder/ixheaace_sbr_main.c
index 893d215..9e13b13 100644
index 893d215..62928da 100644
--- a/encoder/ixheaace_sbr_main.c
+++ b/encoder/ixheaace_sbr_main.c
@@ -100,7 +100,7 @@ FLOAT32 *ixheaace_get_hbe_resample_buffer(ixheaace_pstr_sbr_enc pstr_env_enc) {
@ -489,15 +444,41 @@ index 893d215..9e13b13 100644
*ptr_core_sr = sample_rate_input / 2;
@@ -965,7 +967,7 @@ ixheaace_env_open(ixheaace_pstr_sbr_enc *pstr_env_encoder, ixheaace_pstr_sbr_cfg
pstr_env_enc->str_sbr_cfg.stereo_mode =
(params->codec_settings.num_channels == 2) ? params->stereo_mode : IXHEAACE_SBR_MODE_MONO;
- if (params->codec_settings.sample_freq <= 24000) {
+ if (1) {
pstr_env_enc->str_sbr_hdr.sample_rate_mode = IXHEAACE_DUAL_RATE;
if (params->sbr_codec == USAC_SBR) {
pstr_env_enc->str_sbr_cfg.sample_freq = 2 * params->codec_settings.sample_freq;
diff --git a/encoder/ixheaace_sbr_noise_floor_est.c b/encoder/ixheaace_sbr_noise_floor_est.c
index c5fcd99..344d2b0 100644
--- a/encoder/ixheaace_sbr_noise_floor_est.c
+++ b/encoder/ixheaace_sbr_noise_floor_est.c
@@ -136,8 +136,10 @@ static VOID ia_enhaacplus_enc_qmf_based_noise_floor_detection(
mean_org += ton_org;
mean_sbr += ton_sbr;
}
- mean_org /= (stop_channel - start_channel);
- mean_sbr /= (stop_channel - start_channel);
+ if ((stop_channel - start_channel) > 0) {
+ mean_org /= (stop_channel - start_channel);
+ mean_sbr /= (stop_channel - start_channel);
+ }
}
if (mean_org < SBR_TON_MEAN_P0009 && mean_sbr < SBR_TON_MEAN_P0009) {
diff --git a/encoder/ixheaace_sbr_rom.c b/encoder/ixheaace_sbr_rom.c
index 90e94c5..435fc2e 100644
index 90e94c5..bb52192 100644
--- a/encoder/ixheaace_sbr_rom.c
+++ b/encoder/ixheaace_sbr_rom.c
@@ -48,6 +48,9 @@ const WORD32 vector_offset_def[] = {0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 16, 20, 2
const WORD32 vector_stop_freq_32[14] = {32, 34, 36, 38, 40, 42, 44, 46, 49, 52, 55, 58, 61, 64};
const WORD32 vector_stop_freq_44[14] = {23, 25, 27, 29, 32, 34, 37, 40, 43, 47, 51, 55, 59, 64};
const WORD32 vector_stop_freq_48[14] = {21, 23, 25, 27, 30, 32, 35, 38, 42, 45, 49, 54, 59, 64};
+const WORD32 vector_stop_freq_64[14] = {20, 22, 24, 26, 28, 31, 34, 37, 41, 45, 49, 54, 59, 64};
+const WORD32 vector_stop_freq_64[14] = {20, 22, 24, 26, 29, 31, 34, 37, 41, 45, 49, 54, 59, 64};
+const WORD32 vector_stop_freq_88[14] = {15, 17, 19, 21, 23, 26, 29, 33, 37, 41, 46, 51, 57, 64};
+const WORD32 vector_stop_freq_96[14] = {13, 15, 17, 19, 21, 24, 27, 31, 35, 39, 44, 50, 57, 64};
@ -511,13 +492,13 @@ index 90e94c5..435fc2e 100644
{{{{8000, 10000, {7, 11}, 3, {1, 0, 6}, IXHEAACE_SBR_MODE_MONO},
{10000, 12000, {11, 13}, 3, {1, 0, 6}, IXHEAACE_SBR_MODE_MONO},
{12000, 48001, {14, 13}, 3, {1, 0, 6}, IXHEAACE_SBR_MODE_MONO},
@@ -738,6 +742,238 @@ const ixheaace_str_qmf_tabs ixheaace_qmf_tab = {
@@ -738,6 +742,200 @@ const ixheaace_str_qmf_tabs ixheaace_qmf_tab = {
{0}}}
},
+#else
+ {{{
+ /*** 8000hz 1ch ***/
+ /*** 8000hz 1ch SBR_AAC ***/
+ {8000, 10000, {7, 11}, 3, {1, 0, 6}, IXHEAACE_SBR_MODE_MONO},
+ {10000, 12000, {11, 13}, 3, {1, 0, 6}, IXHEAACE_SBR_MODE_MONO},
+ {12000, 16000, {14, 13}, 3, {1, 0, 6}, IXHEAACE_SBR_MODE_MONO},
@ -526,7 +507,7 @@ index 90e94c5..435fc2e 100644
+ {32000, 48001, {14, 15}, 2, {2, 0, 3}, IXHEAACE_SBR_MODE_MONO},
+ {0}},
+ {
+ /*** 8000hz 2ch ***/
+ /*** 8000hz 2ch SBR_AAC ***/
+ {16000, 24000, {6, 9}, 3, {1, 0, -3}, IXHEAACE_SBR_MODE_SWITCH_LRC},
+ {24000, 28000, {9, 11}, 3, {1, 0, -3}, IXHEAACE_SBR_MODE_SWITCH_LRC},
+ {28000, 36000, {11, 11}, 2, {2, 0, -3}, IXHEAACE_SBR_MODE_SWITCH_LRC},
@ -538,7 +519,7 @@ index 90e94c5..435fc2e 100644
+ {0}}},
+
+ {{
+ /*** 11025hz 1ch ***/
+ /*** 11025hz 1ch SBR_AAC ***/
+ {8000, 10000, {5, 6}, 3, {1, 0, 6}, IXHEAACE_SBR_MODE_MONO},
+ {10000, 12000, {8, 12}, 3, {1, 0, 6}, IXHEAACE_SBR_MODE_MONO},
+ {12000, 16000, {12, 13}, 3, {1, 0, 6}, IXHEAACE_SBR_MODE_MONO},
@ -546,10 +527,10 @@ index 90e94c5..435fc2e 100644
+ {20000, 24000, {13, 13}, 3, {1, 0, 6}, IXHEAACE_SBR_MODE_MONO},
+ {24000, 32000, {14, 14}, 2, {2, 0, 3}, IXHEAACE_SBR_MODE_MONO},
+ {32000, 48000, {15, 15}, 2, {2, 0, 3}, IXHEAACE_SBR_MODE_MONO},
+ {48000, 64001, {15, 15}, 1, {2, 0, 3}, IXHEAACE_SBR_MODE_MONO},
+ {48000, 66001, {15, 15}, 1, {2, 0, 3}, IXHEAACE_SBR_MODE_MONO},
+ {0}},
+ {
+ /*** 11025hz 2ch ***/
+ /*** 11025hz 2ch SBR_AAC ***/
+ {16000, 24000, {7, 9}, 3, {1, 0, -3}, IXHEAACE_SBR_MODE_SWITCH_LRC},
+ {24000, 28000, {10, 10}, 3, {1, 0, -3}, IXHEAACE_SBR_MODE_SWITCH_LRC},
+ {28000, 36000, {12, 12}, 2, {2, 0, -3}, IXHEAACE_SBR_MODE_SWITCH_LRC},
@ -557,11 +538,11 @@ index 90e94c5..435fc2e 100644
+ {44000, 52000, {14, 13}, 2, {2, 0, -3}, IXHEAACE_SBR_MODE_SWITCH_LRC},
+ {52000, 60000, {15, 13}, 1, {3, 0, -3}, IXHEAACE_SBR_MODE_SWITCH_LRC},
+ {60000, 76000, {15, 13}, 1, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ {76000, 128001, {15, 13}, 1, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ {76000, 132301, {15, 13}, 1, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ {0}}},
+
+ {{
+ /*** 12000hz 1ch ***/
+ /*** 12000hz 1ch SBR_AAC ***/
+ {8000, 10000, {4, 6}, 3, {1, 0, 6}, IXHEAACE_SBR_MODE_MONO},
+ {10000, 12000, {7, 11}, 3, {1, 0, 6}, IXHEAACE_SBR_MODE_MONO},
+ {12000, 16000, {11, 12}, 3, {1, 0, 6}, IXHEAACE_SBR_MODE_MONO},
@ -569,10 +550,10 @@ index 90e94c5..435fc2e 100644
+ {20000, 24000, {12, 12}, 3, {1, 0, 6}, IXHEAACE_SBR_MODE_MONO},
+ {24000, 32000, {13, 13}, 2, {2, 0, 3}, IXHEAACE_SBR_MODE_MONO},
+ {32000, 48000, {14, 14}, 2, {2, 0, 3}, IXHEAACE_SBR_MODE_MONO},
+ {48000, 64001, {15, 15}, 1, {2, 0, 3}, IXHEAACE_SBR_MODE_MONO},
+ {48000, 72001, {15, 15}, 1, {2, 0, 3}, IXHEAACE_SBR_MODE_MONO},
+ {0}},
+ {
+ /*** 12000hz 2ch ***/
+ /*** 12000hz 2ch SBR_AAC ***/
+ {16000, 24000, {6, 9}, 3, {1, 0, -3}, IXHEAACE_SBR_MODE_SWITCH_LRC},
+ {24000, 28000, {9, 10}, 3, {1, 0, -3}, IXHEAACE_SBR_MODE_SWITCH_LRC},
+ {28000, 36000, {11, 12}, 2, {2, 0, -3}, IXHEAACE_SBR_MODE_SWITCH_LRC},
@ -580,11 +561,11 @@ index 90e94c5..435fc2e 100644
+ {44000, 52000, {13, 13}, 2, {2, 0, -3}, IXHEAACE_SBR_MODE_SWITCH_LRC},
+ {52000, 60000, {14, 13}, 1, {3, 0, -3}, IXHEAACE_SBR_MODE_SWITCH_LRC},
+ {60000, 76000, {15, 13}, 1, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ {76000, 128001, {15, 13}, 1, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ {76000, 144001, {15, 13}, 1, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ {0}}},
+
+ {{
+ /*** 16000hz 1ch ***/
+ /*** 16000hz 1ch SBR_AAC ***/
+ {6000, 8000, {0, 0}, 3, {1, 0, 6}, IXHEAACE_SBR_MODE_MONO},
+ {8000, 10000, {1, 0}, 3, {1, 0, 6}, IXHEAACE_SBR_MODE_MONO},
+ {10000, 12000, {2, 6}, 3, {1, 0, 6}, IXHEAACE_SBR_MODE_MONO},
@ -594,10 +575,10 @@ index 90e94c5..435fc2e 100644
+ {22000, 28000, {10, 12}, 2, {2, 0, 6}, IXHEAACE_SBR_MODE_MONO},
+ {28000, 36000, {12, 13}, 2, {2, 0, 3}, IXHEAACE_SBR_MODE_MONO},
+ {36000, 44000, {14, 13}, 1, {2, 0, 3}, IXHEAACE_SBR_MODE_MONO},
+ {44000, 64001, {15, 13}, 1, {2, 0, 3}, IXHEAACE_SBR_MODE_MONO},
+ {44000, 96001, {15, 13}, 1, {2, 0, 3}, IXHEAACE_SBR_MODE_MONO},
+ {0}},
+ {
+ /*** 16000hz 2ch ***/
+ /*** 16000hz 2ch SBR_AAC ***/
+ {16000, 24000, {4, 1}, 3, {1, 0, -3}, IXHEAACE_SBR_MODE_SWITCH_LRC},
+ {24000, 28000, {8, 10}, 3, {1, 0, -3}, IXHEAACE_SBR_MODE_SWITCH_LRC},
+ {28000, 36000, {10, 12}, 2, {2, 0, -3}, IXHEAACE_SBR_MODE_SWITCH_LRC},
@ -605,11 +586,11 @@ index 90e94c5..435fc2e 100644
+ {44000, 52000, {15, 13}, 2, {2, 0, -3}, IXHEAACE_SBR_MODE_SWITCH_LRC},
+ {52000, 60000, {15, 13}, 1, {3, 0, -3}, IXHEAACE_SBR_MODE_SWITCH_LRC},
+ {60000, 76000, {15, 13}, 1, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ {76000, 128001, {15, 13}, 1, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ {76000, 192001, {15, 13}, 1, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ {0}}},
+
+ {{
+ /*** 22050hz 1ch ***/
+ /*** 22050hz 1ch SBR_AAC ***/
+ {8000, 11369, {1, 1}, 3, {1, 0, 6}, IXHEAACE_SBR_MODE_MONO},
+ {11369, 16000, {3, 4}, 3, {1, 0, 6}, IXHEAACE_SBR_MODE_MONO},
+ {16000, 18000, {3, 5}, 3, {1, 0, 6}, IXHEAACE_SBR_MODE_MONO},
@ -617,12 +598,10 @@ index 90e94c5..435fc2e 100644
+ {22000, 28000, {7, 8}, 2, {2, 0, 6}, IXHEAACE_SBR_MODE_MONO},
+ {28000, 36000, {10, 9}, 2, {2, 0, 3}, IXHEAACE_SBR_MODE_MONO},
+ {36000, 44000, {11, 10}, 1, {2, 0, 3}, IXHEAACE_SBR_MODE_MONO},
+ {44000, 52000, {13, 11}, 1, {2, 0, 0}, IXHEAACE_SBR_MODE_MONO},
+ {52000, 68000, {14, 12}, 1, {3, 0, -3}, IXHEAACE_SBR_MODE_MONO},
+ {68000, 96001, {14, 12}, 1, {3, 0, -3}, IXHEAACE_SBR_MODE_MONO},
+ {44000, 132151, {13, 12}, 1, {2, 0, 3}, IXHEAACE_SBR_MODE_MONO},
+ {0}},
+ {
+ /*** 22050hz 2ch ***/
+ /*** 22050hz 2ch SBR_AAC ***/
+ {16000, 24000, {2, 1}, 3, {1, 0, -3}, IXHEAACE_SBR_MODE_SWITCH_LRC},
+ {24000, 28000, {5, 6}, 3, {1, 0, -3}, IXHEAACE_SBR_MODE_SWITCH_LRC},
+ {28000, 32000, {5, 8}, 2, {2, 0, -3}, IXHEAACE_SBR_MODE_SWITCH_LRC},
@ -631,11 +610,11 @@ index 90e94c5..435fc2e 100644
+ {44000, 52000, {12, 9}, 2, {3, 0, -3}, IXHEAACE_SBR_MODE_SWITCH_LRC},
+ {52000, 60000, {13, 10}, 1, {3, 0, -3}, IXHEAACE_SBR_MODE_SWITCH_LRC},
+ {60000, 101000, {14, 12}, 1, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ {101000, 128001, {15, 12}, 1, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ {101000, 264601, {15, 12}, 1, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ {0}}},
+
+ {{
+ /*** 24000hz 1ch ***/
+ /*** 24000hz 1ch SBR_AAC ***/
+ {8000, 12000, {1, 1}, 3, {1, 0, 6}, IXHEAACE_SBR_MODE_MONO},
+ {12000, 16000, {3, 4}, 3, {1, 0, 6}, IXHEAACE_SBR_MODE_MONO},
+ {16000, 18000, {3, 5}, 3, {1, 0, 6}, IXHEAACE_SBR_MODE_MONO},
@ -643,12 +622,10 @@ index 90e94c5..435fc2e 100644
+ {22000, 28000, {7, 8}, 2, {2, 0, 6}, IXHEAACE_SBR_MODE_MONO},
+ {28000, 36000, {10, 9}, 2, {2, 0, 3}, IXHEAACE_SBR_MODE_MONO},
+ {36000, 44000, {11, 10}, 1, {2, 0, 3}, IXHEAACE_SBR_MODE_MONO},
+ {44000, 52000, {13, 11}, 1, {3, 0, 0}, IXHEAACE_SBR_MODE_MONO},
+ {52000, 68000, {15, 11}, 1, {3, 0, -3}, IXHEAACE_SBR_MODE_MONO},
+ {68000, 96001, {15, 12}, 1, {3, 0, -3}, IXHEAACE_SBR_MODE_MONO},
+ {44000, 144001, {13, 11}, 1, {2, 0, 3}, IXHEAACE_SBR_MODE_MONO},
+ {0}},
+ {
+ /*** 24000hz 2ch ***/
+ /*** 24000hz 2ch SBR_AAC ***/
+ {16000, 24000, {2, 1}, 3, {1, 0, -3}, IXHEAACE_SBR_MODE_SWITCH_LRC},
+ {24000, 28000, {5, 6}, 3, {1, 0, -3}, IXHEAACE_SBR_MODE_SWITCH_LRC},
+ {28000, 36000, {7, 8}, 2, {2, 0, -3}, IXHEAACE_SBR_MODE_SWITCH_LRC},
@ -656,92 +633,58 @@ index 90e94c5..435fc2e 100644
+ {44000, 52000, {12, 9}, 2, {3, 0, -3}, IXHEAACE_SBR_MODE_SWITCH_LRC},
+ {52000, 60000, {13, 10}, 1, {3, 0, -3}, IXHEAACE_SBR_MODE_SWITCH_LRC},
+ {60000, 76000, {14, 12}, 1, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ {76000, 128001, {15, 12}, 1, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ {76000, 288001, {15, 12}, 1, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ {0}}},
+
+ {{
+ /*** 32000hz 1ch ***/
+ /*** 32000hz 1ch SBR_AAC ***/
+ {24000, 36000, {4, 4}, 3, {2, 0, 3}, IXHEAACE_SBR_MODE_MONO},
+ {36000, 60000, {7, 6}, 2, {2, 0, 3}, IXHEAACE_SBR_MODE_MONO},
+ {60000, 72000, {9, 8}, 1, {2, 0, 3}, IXHEAACE_SBR_MODE_MONO},
+ {72000, 100000, {11, 10}, 1, {2, 0, 3}, IXHEAACE_SBR_MODE_MONO},
+ {100000, 160001, {13, 11}, 1, {2, 0, 3}, IXHEAACE_SBR_MODE_MONO},
+ {100000, 192001, {13, 11}, 1, {2, 0, 3}, IXHEAACE_SBR_MODE_MONO},
+ {0}},
+ {
+ /*** 32000hz 2ch ***/
+ /*** 32000hz 2ch SBR_AAC ***/
+ {32000, 60000, {4, 4}, 3, {2, 0, -3}, IXHEAACE_SBR_MODE_SWITCH_LRC},
+ {60000, 80000, {11, 6}, 2, {3, 0, -3}, IXHEAACE_SBR_MODE_SWITCH_LRC},
+ {80000, 112000, {12, 8}, 1, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ {112000, 144000, {13, 10}, 1, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ {144000, 256001, {13, 11}, 1, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ {60000, 80000, {7, 6}, 2, {3, 0, -3}, IXHEAACE_SBR_MODE_SWITCH_LRC},
+ {80000, 112000, {9, 8}, 1, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ {112000, 144000, {11, 10}, 1, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ {144000, 384001, {13, 11}, 1, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ {0}}},
+
+ {{
+ /*** 44100hz 1ch ***/
+ {12000, 16000, {0, 0}, 0, {2, 0, 3}, IXHEAACE_SBR_MODE_MONO},
+ {16000, 22000, {1, 1}, 0, {2, 0, 3}, IXHEAACE_SBR_MODE_MONO},
+ {22000, 30000, {2, 3}, 0, {2, 0, 3}, IXHEAACE_SBR_MODE_MONO},
+ {30000, 36000, {4, 4}, 0, {2, 0, 3}, IXHEAACE_SBR_MODE_MONO},
+ {36000, 40000, {5, 4}, 0, {2, 0, 3}, IXHEAACE_SBR_MODE_MONO},
+ {40000, 48000, {6, 5}, 0, {2, 0, 3}, IXHEAACE_SBR_MODE_MONO},
+ {48000, 60000, {7, 6}, 1, {3, 0, 3}, IXHEAACE_SBR_MODE_MONO},
+ {60000, 72000, {9, 6}, 1, {3, 0, 0}, IXHEAACE_SBR_MODE_MONO},
+ {72000, 88000, {10, 8}, 1, {3, 0, -3}, IXHEAACE_SBR_MODE_MONO},
+ {88000, 160001, {12, 9}, 1, {3, 0, -3}, IXHEAACE_SBR_MODE_MONO},
+ {160001, 288001, {13, 12}, 1, {3, 0, -3}, IXHEAACE_SBR_MODE_MONO},
+ /*** 44100hz 1ch SBR_AAC ***/
+ {24000, 36000, {4, 4}, 3, {2, 0, 3}, IXHEAACE_SBR_MODE_MONO},
+ {36000, 60000, {7, 6}, 2, {2, 0, 3}, IXHEAACE_SBR_MODE_MONO},
+ {60000, 72000, {9, 8}, 1, {2, 0, 3}, IXHEAACE_SBR_MODE_MONO},
+ {72000, 100000, {11, 10}, 1, {2, 0, 3}, IXHEAACE_SBR_MODE_MONO},
+ {100000, 264601, {13, 11}, 1, {2, 0, 3}, IXHEAACE_SBR_MODE_MONO},
+ {0}},
+ {
+ /*** 44100hz 2ch ***/
+ {12000, 16000, {0, 0}, 0, {2, 0, -3}, IXHEAACE_SBR_MODE_SWITCH_LRC},
+ {16000, 22000, {1, 0}, 0, {2, 0, -3}, IXHEAACE_SBR_MODE_SWITCH_LRC},
+ {22000, 26000, {2, 1}, 0, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ {26000, 30000, {3, 3}, 0, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ {30000, 34000, {3, 3}, 0, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ {34000, 38000, {4, 4}, 0, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ {38000, 44000, {5, 4}, 0, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ {44000, 52000, {6, 4}, 0, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ {52000, 60000, {8, 5}, 2, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ {60000, 68000, {9, 6}, 2, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ {68000, 76000, {10, 6}, 2, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ {76000, 90000, {11, 7}, 1, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ {90000, 112000, {11, 8}, 1, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ {112000, 132000, {12, 9}, 1, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ {132000, 180000, {13, 11}, 1, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ {180000, 288001, {15, 12}, 1, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ /*** 44100hz 2ch SBR_AAC ***/
+ {32000, 60000, {4, 4}, 3, {2, 0, -3}, IXHEAACE_SBR_MODE_SWITCH_LRC},
+ {60000, 80000, {7, 6}, 2, {3, 0, -3}, IXHEAACE_SBR_MODE_SWITCH_LRC},
+ {80000, 112000, {9, 8}, 1, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ {112000, 144000, {11, 10}, 1, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ {144000, 529201, {13, 11}, 1, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ {0}}},
+
+ {{
+ /*** 48000hz 1ch ***/
+ {12000, 16000, {0, 0}, 0, {2, 0, 3}, IXHEAACE_SBR_MODE_MONO},
+ {16000, 22000, {1, 1}, 0, {2, 0, 3}, IXHEAACE_SBR_MODE_MONO},
+ {22000, 30000, {2, 3}, 0, {2, 0, 3}, IXHEAACE_SBR_MODE_MONO},
+ {30000, 36000, {4, 4}, 0, {2, 0, 3}, IXHEAACE_SBR_MODE_MONO},
+ {36000, 40000, {5, 4}, 0, {2, 0, 3}, IXHEAACE_SBR_MODE_MONO},
+ {40000, 48000, {6, 5}, 0, {2, 0, 3}, IXHEAACE_SBR_MODE_MONO},
+ {48000, 60000, {7, 6}, 1, {3, 0, 3}, IXHEAACE_SBR_MODE_MONO},
+ {60000, 72000, {9, 6}, 1, {3, 0, 0}, IXHEAACE_SBR_MODE_MONO},
+ {72000, 88000, {10, 8}, 1, {3, 0, -3}, IXHEAACE_SBR_MODE_MONO},
+ {88000, 160001, {12, 9}, 1, {3, 0, -3}, IXHEAACE_SBR_MODE_MONO},
+ {160001, 288001, {13, 12}, 1, {3, 0, -3}, IXHEAACE_SBR_MODE_MONO},
+ /*** 48000hz 1ch SBR_AAC ***/
+ {24000, 36000, {4, 9}, 3, {2, 0, 3}, IXHEAACE_SBR_MODE_MONO},
+ {36000, 60000, {7, 10}, 2, {2, 0, 3}, IXHEAACE_SBR_MODE_MONO},
+ {60000, 72000, {9, 10}, 1, {2, 0, 3}, IXHEAACE_SBR_MODE_MONO},
+ {72000, 100000, {11, 11}, 1, {2, 0, 3}, IXHEAACE_SBR_MODE_MONO},
+ {100000, 288001, {13, 11}, 1, {2, 0, 3}, IXHEAACE_SBR_MODE_MONO},
+ {0}},
+ {
+ /*** 48000hz 2ch ***/
+ {12000, 16000, {0, 0}, 0, {2, 0, -3}, IXHEAACE_SBR_MODE_SWITCH_LRC},
+ {16000, 22000, {0, 0}, 0, {2, 0, -3}, IXHEAACE_SBR_MODE_SWITCH_LRC},
+ {22000, 26000, {1, 1}, 0, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ {26000, 30000, {2, 3}, 0, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ {30000, 34000, {3, 3}, 0, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ {34000, 38000, {4, 4}, 0, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ {38000, 44000, {2, 4}, 0, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ {44000, 52000, {6, 4}, 0, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ {52000, 60000, {8, 5}, 2, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ {60000, 68000, {9, 6}, 2, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ {68000, 76000, {10, 6}, 2, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ {76000, 90000, {11, 7}, 1, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ {90000, 112000, {11, 8}, 1, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ {112000, 132000, {12, 9}, 1, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ {132000, 180000, {13, 11}, 1, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ {180000, 288001, {15, 12}, 1, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ /*** 48000hz 2ch SBR_AAC ***/
+ {32000, 60000, {4, 9}, 3, {2, 0, -3}, IXHEAACE_SBR_MODE_SWITCH_LRC},
+ {60000, 80000, {7, 10}, 2, {2, 0, -3}, IXHEAACE_SBR_MODE_SWITCH_LRC},
+ {80000, 112000, {9, 10}, 1, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ {112000, 144000, {11, 11}, 1, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ {144000, 576001, {13, 11}, 1, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ {0}}}
+
+ },
@ -750,7 +693,7 @@ index 90e94c5..435fc2e 100644
{{{{0}}},
{{{0}}},
@@ -824,7 +1060,146 @@ const ixheaace_str_qmf_tabs ixheaace_qmf_tab = {
@@ -824,7 +1022,146 @@ const ixheaace_str_qmf_tabs ixheaace_qmf_tab = {
{144000, 176000, {12, 11}, 1, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
{176000, 256001, {13, 11}, 1, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
{0}}}}
@ -762,7 +705,7 @@ index 90e94c5..435fc2e 100644
+ {{
+ /*** 12000hz 1ch ***/
+ {8000, 32000, {1, 0}, 3, {1, 0, 6}, IXHEAACE_SBR_MODE_MONO},
+ {0}},
+ {0}},
+ {
+ {0}}},
+
@ -816,7 +759,7 @@ index 90e94c5..435fc2e 100644
+ {76000, 82000, {12, 11}, 1, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ {82000, 128001, {13, 11}, 1, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ {0}}},
+
+ {{
+ /*** 24000hz 1ch ***/
+ {8000, 12000, {1, 1}, 3, {1, 0, 6}, IXHEAACE_SBR_MODE_MONO},
@ -858,7 +801,7 @@ index 90e94c5..435fc2e 100644
+ {112000, 144000, {11, 10}, 1, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ {144000, 256001, {13, 11}, 1, {3, 0, -3}, IXHEAACE_SBR_MODE_LEFT_RIGHT},
+ {0}}},
+
+ {{
+ /*** 44100hz 1ch ***/
+ {24000, 36000, {4, 9}, 3, {2, 0, 3}, IXHEAACE_SBR_MODE_MONO},

View file

@ -55,6 +55,10 @@ set_target_properties(${target}
#
# Include directories
#
target_link_directories(${target}
PRIVATE
${XAAC_BIN_DIR}
)
target_include_directories(${target}
PRIVATE

View file

@ -78,6 +78,7 @@ int main(int argc, char *argv[]) {
ap.add_argument("input");
ap.add_argument("output");
ap.add_argument("-c", "--conceal").help("Error concealment").flag();
ap.add_argument("-e", "--enhanced-sbr").help("Enhanced SBR").flag();
ap.add_argument("-f", "--frame-size").help("Frame size").default_value(0).scan<'i', int>();
@ -91,12 +92,14 @@ int main(int argc, char *argv[]) {
auto inFile = ap.get<std::string>("input");
auto outFile = ap.get<std::string>("output");
auto errorConceal = ap.get<bool>("-c");
auto eSBR = ap.get<bool>("-e");
auto frameSize = ap.get<int>("-f");
AACDecodeSettings aacConf = {};
aacConf.bitsPerSamples = 16;
aacConf.eSBR = eSBR;
aacConf.errorConceal = errorConceal;
aacConf.frameSize = frameSize;
FILE * inpFile = fopen(inFile.c_str(), "rb");
@ -176,6 +179,7 @@ int main(int argc, char *argv[]) {
int16_t *outBuf = new int16_t[decoder->outBufSize / sizeof(int16_t)];
uint32_t outSize;
uint32_t nBytes;
int32_t res = 0;
ProgressBar bar{
option::BarWidth{50},
@ -246,6 +250,7 @@ int main(int argc, char *argv[]) {
int ret = aac_decode(decoder, readBuf, bufReadSize, (uint8_t *)outBuf, &outSize, &nBytes);
if (ret == -1) {
std::cerr << "Decode frame " << adtsCount << " failed" << std::endl;
res = 1;
break;
}
@ -278,7 +283,9 @@ int main(int argc, char *argv[]) {
}
outpFile.save(outFile);
aac_decode_close(decoder);
return res;
#if 0
#if 0
AACFileReader inData("asc.es", 4096);

View file

@ -67,6 +67,10 @@ target_include_directories(${target}
#
# Libraries
#
target_link_directories(${target}
PRIVATE
${XAAC_BIN_DIR}
)
target_link_libraries(${target}
PRIVATE

View file

@ -59,6 +59,8 @@ add_library(${target}
${headers}
)
add_dependencies(${target} libxaac)
# Create namespaced alias
add_library(${META_PROJECT_NAME}::${target} ALIAS ${target})
@ -128,14 +130,20 @@ target_include_directories(${target}
#
# Libraries
#
target_link_directories(${target}
PRIVATE
${XAAC_BIN_DIR}
)
target_link_libraries(${target}
PRIVATE
libxaacenc
libxaacdec
$<$<BOOL:${BUILD_SHARED_LIBS}>:xaacenc>
$<$<BOOL:${BUILD_SHARED_LIBS}>:xaacdec>
PUBLIC
${DEFAULT_LIBRARIES}
$<$<NOT:$<BOOL:${BUILD_SHARED_LIBS}>>:xaacenc>
$<$<NOT:$<BOOL:${BUILD_SHARED_LIBS}>>:xaacdec>
INTERFACE
)
@ -227,5 +235,13 @@ install(EXPORT ${target}-export
)
# pkg-config
if (BUILD_SHARED_LIBS)
set(LIBAAC_LINKERS "-l${target}")
else()
set(LIBAAC_LINKERS "-l${target} -lxaacenc -lxaacdec -lm")
install(FILES ${PROJECT_BINARY_DIR}/libxaac-prefix/src/libxaac-build/libxaacdec.a DESTINATION ${INSTALL_LIB}/ COMPONENT dev)
install(FILES ${PROJECT_BINARY_DIR}/libxaac-prefix/src/libxaac-build/libxaacenc.a DESTINATION ${INSTALL_LIB}/ COMPONENT dev)
endif()
configure_file(pkg-config.pc.in ${CMAKE_CURRENT_BINARY_DIR}/pkgconfig/${META_PROJECT_NAME}.pc @ONLY)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/pkgconfig/${META_PROJECT_NAME}.pc DESTINATION ${INSTALL_LIB}/pkgconfig COMPONENT dev)

View file

@ -24,6 +24,8 @@ typedef struct {
uint32_t ascSize; // AudioSpecific config size
uint32_t in_buf_offset; // Input buffer offset
int32_t inputDelay; // Input delay
void (* errorHandler)(uint32_t errorCode, const char *section, const char *errorMsg, bool isFatal, void *handle); // Error handler
void * errorHandleCtx; // Error handler object
} AACContext;
typedef struct {
@ -38,6 +40,8 @@ typedef struct {
uint32_t frameSize; // Custom frame size
bool eSBR; // Enhanced SBR
uint32_t iq; // Inverse quant
void (* errorHandler)(uint32_t errorCode, const char *section, const char *errorMsg, bool isFatal, void *handle); // Error handler
void * errorHandleCtx; // Error handler object
} AACSettings;
AACNEXT_API AACContext * aac_encode_open(AACSettings info);
@ -63,6 +67,8 @@ typedef struct {
uint32_t sbrMode; // SBR mode
bool eSBR; // Enhanced SBR
uint64_t frameCounter; // Frame counter
void (* errorHandler)(uint32_t errorCode, const char *section, const char *errorMsg, bool isFatal, void *handle); // Error handler
void * errorHandleCtx; // Error handler object
} AACDecode;
typedef struct {
@ -71,11 +77,16 @@ typedef struct {
uint64_t noChannels; // Number of channels
int32_t bitsPerSamples; // Bits per samples
uint32_t frameSize; // Frame size
bool eSBR; // Enhanced SBR
int32_t eSBR; // Enhanced SBR
int32_t errorConceal; // Error concealment
void (* errorHandler)(uint32_t errorCode, const char *section, const char *errorMsg, bool isFatal, void *handle); // Error handler
void * errorHandleCtx; // Error handler object
} AACDecodeSettings;
AACNEXT_API AACDecode * aac_decode_open(AACDecodeSettings cfg);
AACNEXT_API int aac_decode(AACDecode *aacd, unsigned char *inData, unsigned int inDataSize, unsigned char *outData, unsigned int *outSize, unsigned int *bytesRead);
AACNEXT_API void aac_decode_reset(AACDecode *aacd);
AACNEXT_API void aac_decode_flush_buffer(AACDecode *aacd);
AACNEXT_API void aac_decode_close(AACDecode *aacd);
#ifdef __cplusplus

View file

@ -7,5 +7,5 @@ toolsdir=${exec_prefix}/bin
Name: @PROJECT_NAME@
Description: @PROJECT_DESCRIPTION@
Version: @PROJECT_VERSION@
Libs: -L${libdir} -l@target@
Libs: -L${libdir} @LIBAAC_LINKERS@
Cflags: -I${includedir}

View file

@ -313,14 +313,18 @@ void aac_encode_strerror(unsigned int error, char *errorStr, int *isFatal) {
}
}
int aac_encode_handle_error(IA_ERRORCODE ret, const char *section) {
int aac_encode_handle_error(AACContext * aac, IA_ERRORCODE ret, const char *section) {
char strerror[8192] = {0};
int isFatal;
if (ret == IA_NO_ERROR) return 0;
aac_encode_strerror(ret, strerror, &isFatal);
fprintf(stderr, "libaac%s %s: %s\n", isFatal ? " fatal error:" : "", section, strerror);
if (aac->errorHandler == NULL) {
fprintf(stderr, "libaac%s %s: %s\n", isFatal ? " fatal error:" : "", section, strerror);
} else {
aac->errorHandler(ret, section, strerror, isFatal, aac->errorHandleCtx);
}
return isFatal;
}
@ -431,8 +435,11 @@ AACContext * aac_encode_open(AACSettings info) {
aac_in_config->ui_pcm_wd_sz = info.bitsPerSamples; // Fixed point only although float computing is possible
aac_in_config->aac_config.length = 0;
aac->errorHandler = info.errorHandler;
aac->errorHandleCtx = info.errorHandleCtx;
ret = ixheaace_create(aac->pstr_in_cfg, aac->pstr_out_cfg);
if (aac_encode_handle_error(ret, "init-encoder")) goto fail;
if (aac_encode_handle_error(aac, ret, "init-encoder")) goto fail;
aac->no_samples = aac_out_config->input_size / (aac_in_config->ui_pcm_wd_sz == 32 ? 4 : 2);
aac->max_out_bytes = aac_out_config->mem_info_table[IA_MEMTYPE_OUTPUT].ui_size;
@ -477,7 +484,7 @@ int aac_encode(AACContext *aac, unsigned char *inData, unsigned int inDataSize,
aac->in_buf_offset = 0;
IA_ERRORCODE ret = ixheaace_process(aac_out_config->pv_ia_process_api_obj, aac->pstr_in_cfg, aac->pstr_out_cfg);
if (aac_encode_handle_error(ret, "encode")) return -1;
if (aac_encode_handle_error(aac, ret, "encode")) return -1;
memcpy(outData, aac_out_buf, aac_out_config->i_out_bytes);
*outSize = aac_out_config->i_out_bytes;
@ -650,14 +657,18 @@ void aac_decode_strerror(unsigned int error, char *errorStr, int *isFatal) {
}
}
int aac_decode_handle_error(IA_ERRORCODE ret, const char *section) {
int aac_decode_handle_error(AACDecode * aacDec, IA_ERRORCODE ret, const char *section) {
char strerror[8192] = {0};
int isFatal;
if (ret == IA_NO_ERROR) return 0;
aac_decode_strerror(ret, strerror, &isFatal);
fprintf(stderr, "libaac%s %s: %s\n", isFatal ? " fatal error:" : "", section, strerror);
if (aacDec->errorHandler == NULL) {
fprintf(stderr, "libaac%s %s: %s\n", isFatal ? " fatal error:" : "", section, strerror);
} else {
aacDec->errorHandler(ret, section, strerror, isFatal, aacDec->errorHandleCtx);
}
return isFatal;
}
@ -679,27 +690,33 @@ AACDecode * aac_decode_open(AACDecodeSettings cfg) {
if (aacDec->apiObj == NULL) goto fail;
/* 02 - API Init */
aacDec->errorHandler = cfg.errorHandler;
aacDec->errorHandleCtx = cfg.errorHandleCtx;
ret = ixheaacd_dec_api(aacDec->apiObj, IA_API_CMD_INIT, IA_CMD_TYPE_INIT_API_PRE_CONFIG_PARAMS, NULL);
if (aac_decode_handle_error(ret, "preconfig")) goto fail;
if (aac_decode_handle_error(aacDec, ret, "preconfig")) goto fail;
/* 03 - Configuration starts here */
int isMP4 = cfg.ascSize > 0;
ret = ixheaacd_dec_api(aacDec->apiObj, IA_API_CMD_SET_CONFIG_PARAM, IA_ENHAACPLUS_DEC_CONFIG_PARAM_ISMP4, &isMP4);
if (aac_decode_handle_error(ret, "updating mp4 flag")) goto fail;
if (aac_decode_handle_error(aacDec, ret, "updating mp4 flag")) goto fail;
ret = ixheaacd_dec_api(aacDec->apiObj, IA_API_CMD_SET_CONFIG_PARAM, IA_ENHAACPLUS_DEC_CONFIG_PARAM_PCM_WDSZ, &cfg.bitsPerSamples);
if (aac_decode_handle_error(ret, "updating bits per samples")) goto fail;
if (aac_decode_handle_error(aacDec, ret, "updating bits per samples")) goto fail;
int is480FrameSize = cfg.frameSize == 480;
ret = ixheaacd_dec_api(aacDec->apiObj, IA_API_CMD_SET_CONFIG_PARAM, IA_ENHAACPLUS_DEC_CONFIG_PARAM_FRAMESIZE, &is480FrameSize);
if (aac_decode_handle_error(ret, "updating frame length (ld)")) goto fail;
if (aac_decode_handle_error(aacDec, ret, "updating frame length (ld)")) goto fail;
int is960FrameSize = cfg.frameSize == 960;
ret = ixheaacd_dec_api(aacDec->apiObj, IA_API_CMD_SET_CONFIG_PARAM, IA_ENHAACPLUS_DEC_CONFIG_PARAM_FRAMELENGTH_FLAG, &is960FrameSize);
if (aac_decode_handle_error(ret, "updating frame length")) goto fail;
if (aac_decode_handle_error(aacDec, ret, "updating frame length")) goto fail;
ret = ixheaacd_dec_api(aacDec->apiObj, IA_API_CMD_SET_CONFIG_PARAM, IA_XHEAAC_DEC_CONFIG_PARAM_ESBR, &cfg.eSBR);
if (aac_decode_handle_error(ret, "updating esbr")) goto fail;
if (aac_decode_handle_error(aacDec, ret, "updating esbr")) goto fail;
ret = ixheaacd_dec_api(aacDec->apiObj, IA_API_CMD_SET_CONFIG_PARAM, IA_XHEAAC_DEC_CONFIG_ERROR_CONCEALMENT, &cfg.errorConceal);
if (aac_decode_handle_error(aacDec, ret, "updating error conceal")) goto fail;
aacDec->eSBR = cfg.eSBR;
aacDec->asc = cfg.asc;
@ -708,32 +725,32 @@ AACDecode * aac_decode_open(AACDecodeSettings cfg) {
/* 04 - Decoder Memory */
ret = ixheaacd_dec_api(aacDec->apiObj, IA_API_CMD_GET_MEMTABS_SIZE, 0, &mem_info_size);
if (aac_decode_handle_error(ret, "memtab size")) goto fail;
if (aac_decode_handle_error(aacDec, ret, "memtab size")) goto fail;
aacDec->memInfoTab = malloc(mem_info_size);
if (aacDec->memInfoTab == NULL) goto fail;
ret = ixheaacd_dec_api(aacDec->apiObj, IA_API_CMD_SET_MEMTABS_PTR, 0, aacDec->memInfoTab);
if (aac_decode_handle_error(ret, "set memtabs ptr")) goto fail;
if (aac_decode_handle_error(aacDec, ret, "set memtabs ptr")) goto fail;
/* 05 - Post Config */
ret = ixheaacd_dec_api(aacDec->apiObj, IA_API_CMD_INIT, IA_CMD_TYPE_INIT_API_POST_CONFIG_PARAMS, NULL);
if (aac_decode_handle_error(ret, "postconfig")) goto fail;
if (aac_decode_handle_error(aacDec, ret, "postconfig")) goto fail;
for (int i = 0; i < 4; i++) {
int ui_size = 0, ui_alignment = 0, ui_type = 0;
/* Get memory size */
ret = ixheaacd_dec_api(aacDec->apiObj, IA_API_CMD_GET_MEM_INFO_SIZE, i, &ui_size);
if (aac_decode_handle_error(ret, "get meminfo 1")) goto fail;
if (aac_decode_handle_error(aacDec, ret, "get meminfo 1")) goto fail;
/* Get memory alignment */
ret = ixheaacd_dec_api(aacDec->apiObj, IA_API_CMD_GET_MEM_INFO_ALIGNMENT, i, &ui_alignment);
if (aac_decode_handle_error(ret, "get meminfo 2")) goto fail;
if (aac_decode_handle_error(aacDec, ret, "get meminfo 2")) goto fail;
/* Get memory type */
ret = ixheaacd_dec_api(aacDec->apiObj, IA_API_CMD_GET_MEM_INFO_TYPE, i, &ui_type);
if (aac_decode_handle_error(ret, "get meminfo 3")) goto fail;
if (aac_decode_handle_error(aacDec, ret, "get meminfo 3")) goto fail;
ui_alignment = (ui_alignment + sizeof(void *) - 1) / sizeof(void *);
ui_alignment = ui_alignment * sizeof(void *);
@ -746,7 +763,7 @@ AACDecode * aac_decode_open(AACDecodeSettings cfg) {
/* Set the buffer pointer */
ret = ixheaacd_dec_api(aacDec->apiObj, IA_API_CMD_SET_MEM_PTR, i, temp);
if (aac_decode_handle_error(ret, "set meminfo")) goto fail;
if (aac_decode_handle_error(aacDec, ret, "set meminfo")) goto fail;
aacDec->memBuffer[i] = temp;
@ -763,7 +780,7 @@ AACDecode * aac_decode_open(AACDecodeSettings cfg) {
fail:
if (aacDec) {
for (int i = 0; i < 4; i++) free(aacDec->memBuffer[i]);
for (int i = 0; i < 4; i++) free_global(aacDec->memBuffer[i]);
free(aacDec->memInfoTab);
free(aacDec->apiObj);
@ -777,29 +794,33 @@ void aac_decode_write_buffer(AACDecode *aacd, unsigned char *data, unsigned int
memcpy(aacd->inBuf, data, dataSize);
ret = ixheaacd_dec_api(aacd->apiObj, IA_API_CMD_SET_INPUT_BYTES, 0, &dataSize);
aac_decode_handle_error(ret, "upload buffer");
aac_decode_handle_error(aacd, ret, "upload buffer");
}
int aac_decode_init(AACDecode *aacd, bool *isInitDone, unsigned int *noBytes) {
IA_ERRORCODE ret;
int done;
ret = ixheaacd_dec_api(aacd->apiObj, IA_API_CMD_INIT, IA_CMD_TYPE_INIT_PROCESS, NULL);
ixheaacd_dec_api(aacd->apiObj, IA_API_CMD_INIT, IA_CMD_TYPE_INIT_DONE_QUERY, isInitDone);
ixheaacd_dec_api(aacd->apiObj, IA_API_CMD_INIT, IA_CMD_TYPE_INIT_DONE_QUERY, &done);
ixheaacd_dec_api(aacd->apiObj, IA_API_CMD_GET_CURIDX_INPUT_BUF, 0, noBytes);
*isInitDone = done;
return ret;
}
int aac_decode_execute(AACDecode *aacd, bool *isDone, unsigned int *noBytesIn, int *preroll) {
IA_ERRORCODE ret;
int done;
ret = ixheaacd_dec_api(aacd->apiObj, IA_API_CMD_EXECUTE, IA_CMD_TYPE_DO_EXECUTE, NULL);
ixheaacd_dec_api(aacd->apiObj, IA_API_CMD_EXECUTE, IA_CMD_TYPE_DONE_QUERY, isDone);
ixheaacd_dec_api(aacd->apiObj, IA_API_CMD_EXECUTE, IA_CMD_TYPE_DONE_QUERY, &done);
ixheaacd_dec_api(aacd->apiObj, IA_API_CMD_GET_CURIDX_INPUT_BUF, 0, noBytesIn);
ixheaacd_dec_api(aacd->apiObj, IA_API_CMD_GET_CONFIG_PARAM, IA_ENHAACPLUS_DEC_CONFIG_GET_NUM_PRE_ROLL_FRAMES, preroll);
*isDone = done;
return ret;
}
@ -814,7 +835,7 @@ int aac_decode(AACDecode *aacd, unsigned char *inData, unsigned int inDataSize,
if (aacd->ascSize > 0 && !aacd->ascDone) {
aac_decode_write_buffer(aacd, aacd->asc, aacd->ascSize);
ret = aac_decode_init(aacd, &aacd->isInitDone, bytesRead);
if (aac_decode_handle_error(ret, "init-decoder")) return -1;
if (aac_decode_handle_error(aacd, ret, "init-decoder")) return -1;
aacd->ascDone = 1;
timeInited++;
@ -822,7 +843,7 @@ int aac_decode(AACDecode *aacd, unsigned char *inData, unsigned int inDataSize,
aac_decode_write_buffer(aacd, inData, inDataSize);
ret = aac_decode_init(aacd, &aacd->isInitDone, bytesRead);
if (aac_decode_handle_error(ret, "init-decoder")) return -1;
if (aac_decode_handle_error(aacd, ret, "init-decoder")) return -1;
if (ret == IA_XHEAAC_DEC_EXE_NONFATAL_INSUFFICIENT_INPUT_BYTES) return 0;
@ -855,14 +876,14 @@ int aac_decode(AACDecode *aacd, unsigned char *inData, unsigned int inDataSize,
aac_decode_write_buffer(aacd, inData, inDataSize);
ret = aac_decode_execute(aacd, &isDecodeDone, bytesRead, &prerolls);
if (aac_decode_handle_error(ret, "decode")) return -1;
if (aac_decode_handle_error(aacd, ret, "decode")) return -1;
int prerollOffset = 0;
*outSize = 0;
do {
ret = ixheaacd_dec_api(aacd->apiObj, IA_API_CMD_GET_OUTPUT_BYTES, 0, &outByteTemp);
if (aac_decode_handle_error(ret, "preroll handling")) return -1;
if (aac_decode_handle_error(aacd, ret, "preroll handling")) return -1;
if (aacd->sbrMode && (aacd->aot < 23) && aacd->eSBR) {
if (aacd->frameCounter > 0)
@ -882,9 +903,31 @@ int aac_decode(AACDecode *aacd, unsigned char *inData, unsigned int inDataSize,
return 1;
}
void aac_decode_reset(AACDecode *aacd) {
ixheaacd_dec_api(aacd->apiObj, IA_API_CMD_INIT, IA_CMD_TYPE_GA_HDR, NULL);
ixheaacd_dec_api(aacd->apiObj, IA_API_CMD_INIT, IA_CMD_TYPE_GA_HDR, NULL);
aacd->isInitDone = false;
aacd->ascDone = false;
int isMP4 = aacd->ascSize > 0;
ixheaacd_dec_api(aacd->apiObj, IA_API_CMD_SET_CONFIG_PARAM, IA_ENHAACPLUS_DEC_CONFIG_PARAM_ISMP4, &isMP4);
}
void aac_decode_flush_buffer(AACDecode *aacd) {
ixheaacd_dec_api(aacd->apiObj, IA_API_CMD_INIT, IA_CMD_TYPE_FLUSH_MEM, NULL);
ixheaacd_dec_api(aacd->apiObj, IA_API_CMD_INIT, IA_CMD_TYPE_FLUSH_MEM, NULL);
aacd->isInitDone = false;
aacd->ascDone = false;
int isMP4 = aacd->ascSize > 0;
ixheaacd_dec_api(aacd->apiObj, IA_API_CMD_SET_CONFIG_PARAM, IA_ENHAACPLUS_DEC_CONFIG_PARAM_ISMP4, &isMP4);
}
void aac_decode_close(AACDecode *aacd) {
ixheaacd_dec_api(aacd->apiObj, IA_API_CMD_INPUT_OVER, 0, NULL);
for (int i = 0; i < 4; i++) free(aacd->memBuffer[i]);
for (int i = 0; i < 4; i++) free_global(aacd->memBuffer[i]);
free(aacd->memInfoTab);
free(aacd->apiObj);