From: Ray Woo <wr.ray...@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.ray...@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 +@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 +@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.ray...@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 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".