[FFmpeg-devel] [PATCH 1/1] avcodec/libhelix-aac: add aac decoding via libhelix.
wr.raywoo at gmail.com
wr.raywoo at gmail.com
Sun May 18 14:34:51 EEST 2025
From: Ray Woo <wr.raywoo at gmail.com>
libhelix-aac decoder is a kind of fixed-point HE-AAC decoder developed by RealNetworks, 2005.
It behaviours well in embeded platforms where resources are limited.
Signed-off-by: Ray Woo <wr.raywoo at gmail.com>
---
Changelog | 1 +
configure | 6 ++
doc/general_contents.texi | 10 +++
libavcodec/Makefile | 1 +
libavcodec/allcodecs.c | 1 +
libavcodec/libhelix-aacdec.c | 161 +++++++++++++++++++++++++++++++++++
libavcodec/version.h | 4 +-
7 files changed, 182 insertions(+), 2 deletions(-)
create mode 100644 libavcodec/libhelix-aacdec.c
diff --git a/Changelog b/Changelog
index 4217449438..0c852a082a 100644
--- a/Changelog
+++ b/Changelog
@@ -18,6 +18,7 @@ version <next>:
- APV encoding support through a libopenapv wrapper
- VVC decoder supports all content of SCC (Screen Content Coding):
IBC (Inter Block Copy), Palette Mode and ACT (Adaptive Color Transform
+- libhelix-aac decoder
version 7.1:
diff --git a/configure b/configure
index 0609dac4ab..13adc215a5 100755
--- a/configure
+++ b/configure
@@ -213,6 +213,7 @@ External library support:
--enable-ladspa enable LADSPA audio filtering [no]
--enable-lcms2 enable ICC profile support via LittleCMS 2 [no]
--enable-libaom enable AV1 video encoding/decoding via libaom [no]
+ --enable-libhelix-aac enable aac decoding via libhelix-aac for Arduino [no]
--enable-libaribb24 enable ARIB text and caption decoding via libaribb24 [no]
--enable-libaribcaption enable ARIB text and caption decoding via libaribcaption [no]
--enable-libass enable libass subtitles rendering,
@@ -1938,6 +1939,7 @@ EXTERNAL_LIBRARY_LIST="
libfreetype
libfribidi
libharfbuzz
+ libhelix_aac
libglslang
libgme
libgsm
@@ -3579,6 +3581,7 @@ libgsm_decoder_deps="libgsm"
libgsm_encoder_deps="libgsm"
libgsm_ms_decoder_deps="libgsm"
libgsm_ms_encoder_deps="libgsm"
+libhelix_aac_decoder_deps="libhelix_aac"
libilbc_decoder_deps="libilbc"
libilbc_encoder_deps="libilbc"
libjxl_anim_decoder_deps="libjxl libjxl_threads"
@@ -6971,6 +6974,9 @@ enabled libfontconfig && require_pkg_config libfontconfig fontconfig "fontco
enabled libfreetype && require_pkg_config libfreetype freetype2 "ft2build.h FT_FREETYPE_H" FT_Init_FreeType
enabled libfribidi && require_pkg_config libfribidi fribidi fribidi.h fribidi_version_info
enabled libharfbuzz && require_pkg_config libharfbuzz harfbuzz hb.h hb_buffer_create
+enabled libhelix-aac && require libhelix-aac libhelix-aac/aacdec.h AACDecode -lhelix-aac -lstdc++ &&
+ { check_lib libhelix-aac "libhelix-aac/aacdec.h" AACInitDecoder -lhelix-aac -lstdc++ ||
+ die "ERROR: libhelix-aac not found"; }
enabled libglslang && { check_lib spirv_compiler glslang/Include/glslang_c_interface.h glslang_initialize_process \
-lglslang -lMachineIndependent -lGenericCodeGen \
-lSPVRemapper -lSPIRV -lSPIRV-Tools-opt -lSPIRV-Tools -lpthread -lstdc++ -lm ||
diff --git a/doc/general_contents.texi b/doc/general_contents.texi
index 0e6b9570a4..201e57eb98 100644
--- a/doc/general_contents.texi
+++ b/doc/general_contents.texi
@@ -173,6 +173,16 @@ enable it.
LCEVCdec is under the BSD-3-Clause-Clear License.
@end float
+ at section libhelix-aac
+
+libelix-aac decoder is a fixed-point HE-AAC decoder developed by RealNetworks,
+which performs well for 32-bit fixed-point processors. FFmpeg can make use of the
+libhelix-aac library for aac decoding.
+
+Go to @url{https://github.com/pschatzmann/arduino-libhelix} and follow the
+instructions for installing the libhelix-aac library. Then pass
+ at code{--enable-libhelix-aac} to configure to enable it.
+
@section libilbc
iLBC is a narrowband speech codec that has been made freely available
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 77734dff24..c43a24d027 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -1143,6 +1143,7 @@ OBJS-$(CONFIG_LIBGSM_DECODER) += libgsmdec.o
OBJS-$(CONFIG_LIBGSM_ENCODER) += libgsmenc.o
OBJS-$(CONFIG_LIBGSM_MS_DECODER) += libgsmdec.o
OBJS-$(CONFIG_LIBGSM_MS_ENCODER) += libgsmenc.o
+OBJS-$(CONFIG_LIBHELIX_AAC_DECODER) += libhelix-aacdec.o mpeg4audio.o mpeg4audio_sample_rates.o
OBJS-$(CONFIG_LIBILBC_DECODER) += libilbc.o
OBJS-$(CONFIG_LIBILBC_ENCODER) += libilbc.o
OBJS-$(CONFIG_LIBJXL_DECODER) += libjxldec.o libjxl.o
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index cd4f6ecd59..c1fc526535 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -778,6 +778,7 @@ extern const FFCodec ff_libgsm_encoder;
extern const FFCodec ff_libgsm_decoder;
extern const FFCodec ff_libgsm_ms_encoder;
extern const FFCodec ff_libgsm_ms_decoder;
+extern const FFCodec ff_libhelix_aac_decoder;
extern const FFCodec ff_libilbc_encoder;
extern const FFCodec ff_libilbc_decoder;
extern const FFCodec ff_libjxl_anim_decoder;
diff --git a/libavcodec/libhelix-aacdec.c b/libavcodec/libhelix-aacdec.c
new file mode 100644
index 0000000000..8bae6aad7c
--- /dev/null
+++ b/libavcodec/libhelix-aacdec.c
@@ -0,0 +1,161 @@
+/*
+ * libhelix aac decoder
+ * Copyright (C) 2025 Ray Woo <wr.raywoo at gmail.com>
+ *
+ * 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 decoder implementation using Helix lib
+ */
+
+#include "avcodec.h"
+#include "internal.h"
+#include "codec_internal.h"
+#include "decode.h"
+#include "get_bits.h"
+#include "mpeg4audio.h"
+#include "libavutil/intreadwrite.h"
+#include "libavutil/mem.h"
+
+#include <aacdec.h>
+#include <aaccommon.h>
+
+#define SYNCWORDH 0xff
+#define SYNCWORDL 0xf0
+#define LIBHELIX_AAC_MAX_CHANNELS 2
+#define LIBHELIX_AAC_MAX_NSAMPS 2048
+
+typedef struct HAACDecContext {
+ AVClass *class;
+ HAACDecoder context;
+ uint8_t *pcm;
+ int pcm_size;
+ MPEG4AudioConfig m4ac;
+} HAACDecContext;
+
+static av_cold int aac_decode_init(AVCodecContext *avctx)
+{
+ HAACDecContext *aac = avctx->priv_data;
+ GetBitContext gb;
+ int ret;
+
+ aac->context = AACInitDecoder();
+ if (!aac->context)
+ return AVERROR(ENOMEM);
+
+
+ avctx->sample_fmt = AV_SAMPLE_FMT_S16;
+ aac->pcm_size = LIBHELIX_AAC_MAX_NSAMPS * LIBHELIX_AAC_MAX_CHANNELS *
+ av_get_bytes_per_sample(avctx->sample_fmt);
+
+ aac->pcm = av_malloc(aac->pcm_size);
+ if (!aac->pcm)
+ return AVERROR(ENOMEM);
+
+ if (avctx->extradata_size > 0) {
+ if ((ret = init_get_bits(&gb, avctx->extradata, avctx->extradata_size)) < 0)
+ return ret;
+
+ if ((ret = ff_mpeg4audio_get_config_gb(&aac->m4ac, &gb, 1, NULL)) < 0)
+ return ret;
+
+ }
+
+ return 0;
+}
+
+static int aac_decode_frame(AVCodecContext *avctx, AVFrame *frame,
+ int *got_frame_ptr, AVPacket *avpkt)
+{
+ HAACDecContext *aac = avctx->priv_data;
+ AACFrameInfo info;
+ uint8_t *in_data;
+ int ret, in_size;
+
+ if (!aac)
+ return AVERROR(EIO);
+
+ in_data = avpkt->data;
+ in_size = avpkt->size;
+
+ if ((in_data[0] & SYNCWORDH) != SYNCWORDH || (in_data[1] & SYNCWORDL) != SYNCWORDL) {
+ info.sampRateCore = aac->m4ac.sample_rate ? aac->m4ac.sample_rate : avctx->sample_rate;
+ info.nChans = aac->m4ac.channels ? aac->m4ac.channels : avctx->ch_layout.nb_channels;
+ info.profile = AAC_PROFILE_LC;
+ ret = AACSetRawBlockParams(aac->context, 0, &info);
+ if (ret < 0)
+ return ret;
+ }
+
+ ret = AACDecode(aac->context, &in_data, &in_size, (int16_t *)aac->pcm);
+ if (ret < 0) {
+ av_log(avctx, AV_LOG_ERROR, "%s error ret %d.\n", __func__, ret);
+ AACFlushCodec(aac->context);
+ return ret;
+ }
+
+ AACGetLastFrameInfo(aac->context, &info);
+
+ if (!avctx->sample_rate)
+ avctx->sample_rate = info.sampRateOut;
+
+ if (!avctx->ch_layout.nb_channels)
+ av_channel_layout_default(&avctx->ch_layout, info.nChans);
+
+ avctx->frame_size = info.outputSamps / info.nChans;
+
+ frame->nb_samples = avctx->frame_size;
+ if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
+ return ret;
+
+ memcpy(frame->extended_data[0], aac->pcm,
+ avctx->ch_layout.nb_channels * avctx->frame_size *
+ av_get_bytes_per_sample(avctx->sample_fmt));
+
+ *got_frame_ptr = 1;
+
+ return avpkt->size - in_size;
+}
+
+static av_cold int aac_decode_close(AVCodecContext *avctx)
+{
+ HAACDecContext *aac = avctx->priv_data;
+
+ if (aac->context)
+ AACFreeDecoder(aac->context);
+ av_freep(&aac->pcm);
+
+ return 0;
+}
+
+const FFCodec ff_libhelix_aac_decoder = {
+ .p.name = "libhelix_aac",
+ .p.long_name = NULL_IF_CONFIG_SMALL("libHelix AAC Decoder"),
+ .p.type = AVMEDIA_TYPE_AUDIO,
+ .p.id = AV_CODEC_ID_AAC,
+ .priv_data_size = sizeof(HAACDecContext),
+ .init = aac_decode_init,
+ FF_CODEC_DECODE_CB(aac_decode_frame),
+ .close = aac_decode_close,
+ .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF | AV_CODEC_CAP_DR1,
+ .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16,
+ AV_SAMPLE_FMT_NONE },
+ .p.ch_layouts = (const AVChannelLayout[]) { AV_CHANNEL_LAYOUT_MONO,
+ AV_CHANNEL_LAYOUT_STEREO, { 0 } },
+};
diff --git a/libavcodec/version.h b/libavcodec/version.h
index eedf4c5a92..06631ffa8c 100644
--- a/libavcodec/version.h
+++ b/libavcodec/version.h
@@ -29,8 +29,8 @@
#include "version_major.h"
-#define LIBAVCODEC_VERSION_MINOR 3
-#define LIBAVCODEC_VERSION_MICRO 101
+#define LIBAVCODEC_VERSION_MINOR 4
+#define LIBAVCODEC_VERSION_MICRO 100
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
LIBAVCODEC_VERSION_MINOR, \
--
2.34.1
More information about the ffmpeg-devel
mailing list