365 lines
13 KiB
Diff
365 lines
13 KiB
Diff
diff -ruN ffmpeg-7.1.1/configure ffmpeg-7.1.1-custom/configure
|
|
--- ffmpeg-7.1.1/configure 2025-03-03 07:22:08.000000000 +0700
|
|
+++ ffmpeg-7.1.1-custom/configure 2025-07-14 08:24:16.313972645 +0700
|
|
@@ -213,6 +213,7 @@
|
|
--enable-jni enable JNI support [no]
|
|
--enable-ladspa enable LADSPA audio filtering [no]
|
|
--enable-lcms2 enable ICC profile support via LittleCMS 2 [no]
|
|
+ --enable-libaacplus enable AAC encoding using custom libaacplus [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]
|
|
@@ -1874,6 +1875,10 @@
|
|
libxvid
|
|
"
|
|
|
|
+EXTERNAL_LIBRARY_RESTRICTED_LIST="
|
|
+ libaacplus
|
|
+"
|
|
+
|
|
EXTERNAL_LIBRARY_NONFREE_LIST="
|
|
decklink
|
|
libfdk_aac
|
|
@@ -1896,6 +1901,7 @@
|
|
"
|
|
|
|
EXTERNAL_LIBRARY_LIST="
|
|
+ $EXTERNAL_LIBRARY_RESTRICTED_LIST
|
|
$EXTERNAL_LIBRARY_GPL_LIST
|
|
$EXTERNAL_LIBRARY_NONFREE_LIST
|
|
$EXTERNAL_LIBRARY_VERSION3_LIST
|
|
@@ -3512,6 +3518,7 @@
|
|
hevc_videotoolbox_encoder_select="atsc_a53 videotoolbox_encoder"
|
|
prores_videotoolbox_encoder_deps="pthreads"
|
|
prores_videotoolbox_encoder_select="videotoolbox_encoder"
|
|
+libaacplus_encoder_deps="libaacplus"
|
|
libaom_av1_decoder_deps="libaom"
|
|
libaom_av1_encoder_deps="libaom"
|
|
libaom_av1_encoder_select="extract_extradata_bsf dovi_rpuenc"
|
|
@@ -4502,7 +4509,7 @@
|
|
map "die_license_disabled version3" $EXTERNAL_LIBRARY_VERSION3_LIST $EXTERNAL_LIBRARY_GPLV3_LIST
|
|
|
|
enabled gpl && map "die_license_disabled_gpl nonfree" $EXTERNAL_LIBRARY_NONFREE_LIST
|
|
-map "die_license_disabled nonfree" $HWACCEL_LIBRARY_NONFREE_LIST
|
|
+map "die_license_disabled nonfree" $HWACCEL_LIBRARY_NONFREE_LIST $EXTERNAL_LIBRARY_RESTRICTED_LIST
|
|
|
|
enabled version3 && { enabled gpl && enable gplv3 || enable lgplv3; }
|
|
|
|
@@ -6865,6 +6872,7 @@
|
|
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 libaacplus && require_pkg_config libaacplus "aacplus >= 3.0.0" aacplus.h aacplusEncOpen
|
|
enabled libaom && require_pkg_config libaom "aom >= 2.0.0" aom/aom_codec.h aom_codec_version
|
|
enabled libaribb24 && { check_pkg_config libaribb24 "aribb24 > 1.0.3" "aribb24/aribb24.h" arib_instance_new ||
|
|
{ enabled gpl && require_pkg_config libaribb24 aribb24 "aribb24/aribb24.h" arib_instance_new; } ||
|
|
diff -ruN ffmpeg-7.1.1/libavcodec/allcodecs.c ffmpeg-7.1.1-custom/libavcodec/allcodecs.c
|
|
--- ffmpeg-7.1.1/libavcodec/allcodecs.c 2024-09-30 06:31:47.000000000 +0700
|
|
+++ ffmpeg-7.1.1-custom/libavcodec/allcodecs.c 2025-07-14 08:19:18.226168604 +0700
|
|
@@ -756,6 +756,7 @@
|
|
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_libaacplus_encoder;
|
|
extern FFCodec ff_libaom_av1_encoder;
|
|
/* preferred over libaribb24 */
|
|
extern const FFCodec ff_libaribcaption_decoder;
|
|
diff -ruN ffmpeg-7.1.1/libavcodec/libaacplus.c ffmpeg-7.1.1-custom/libavcodec/libaacplus.c
|
|
--- ffmpeg-7.1.1/libavcodec/libaacplus.c 1970-01-01 07:00:00.000000000 +0700
|
|
+++ ffmpeg-7.1.1-custom/libavcodec/libaacplus.c 2025-07-14 09:42:49.266275099 +0700
|
|
@@ -0,0 +1,284 @@
|
|
+/*
|
|
+ * Interface to libaacplus for aac encoding
|
|
+ * Copyright (c) 2010 tipok <piratfm@gmail.com>, 2021-2024 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 libaacplus encoder.
|
|
+ */
|
|
+
|
|
+#include <aacplus.h>
|
|
+
|
|
+#include "libavutil/channel_layout.h"
|
|
+#include "libavutil/common.h"
|
|
+#include "libavutil/intreadwrite.h"
|
|
+#include "libavutil/opt.h"
|
|
+#include "avcodec.h"
|
|
+#include "audio_frame_queue.h"
|
|
+#include "codec_internal.h"
|
|
+#include "encode.h"
|
|
+#include "profiles.h"
|
|
+
|
|
+#define AACENC_BLOCKSIZE 1024
|
|
+#define CORE_DELAY (1600)
|
|
+/* (96-64) makes AAC still some 64 core samples too early wrt SBR ... maybe -32 would be even more correct, but 1024-32 would need additional SBR bitstream delay by one frame */
|
|
+#define CORE_INPUT_OFFSET_PS (0)
|
|
+/* ((1600 (core codec)*2 (multi rate) + 6*64 (sbr dec delay) - 2048 (sbr enc delay) + magic*/
|
|
+#define INPUT_DELAY ((CORE_DELAY) * 2 + 6 * 64 - (AACENC_BLOCKSIZE * 2) + 1)
|
|
+
|
|
+typedef struct aacPlusAudioContext
|
|
+{
|
|
+ const AVClass *class;
|
|
+ aacplusEncHandle aacplus_handle;
|
|
+ unsigned long max_output_bytes;
|
|
+ unsigned long samples_input;
|
|
+ int delay_sent;
|
|
+
|
|
+ AudioFrameQueue afq;
|
|
+} aacPlusAudioContext;
|
|
+
|
|
+static const AVOption aac_enc_options[] = {
|
|
+ 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 av_cold int aacPlus_encode_init(AVCodecContext *avctx)
|
|
+{
|
|
+ aacPlusAudioContext *s = avctx->priv_data;
|
|
+ aacplusEncConfiguration *aacplus_cfg;
|
|
+ int flag_aacplus = (avctx->profile != AV_PROFILE_AAC_LOW && avctx->profile != AV_PROFILE_UNKNOWN);
|
|
+
|
|
+ /* number of channels */
|
|
+ if (avctx->ch_layout.nb_channels < 1 || avctx->ch_layout.nb_channels > 2)
|
|
+ {
|
|
+ av_log(avctx, AV_LOG_ERROR, "encoding %d channel(s) is not allowed\n", avctx->ch_layout.nb_channels);
|
|
+ return AVERROR(EINVAL);
|
|
+ }
|
|
+
|
|
+ if (avctx->profile != AV_PROFILE_AAC_LOW && avctx->profile != AV_PROFILE_AAC_HE && avctx->profile != AV_PROFILE_UNKNOWN)
|
|
+ {
|
|
+ av_log(avctx, AV_LOG_ERROR, "invalid AAC profile: %d, only LC and HE-AAC were supported\n", avctx->profile);
|
|
+ return AVERROR(EINVAL);
|
|
+ }
|
|
+
|
|
+ s->aacplus_handle = aacplusEncOpen(avctx->sample_rate, avctx->ch_layout.nb_channels, &s->samples_input, &s->max_output_bytes, flag_aacplus);
|
|
+
|
|
+ if (!s->aacplus_handle)
|
|
+ {
|
|
+ av_log(avctx, AV_LOG_ERROR, "can't open encoder\n");
|
|
+ return AVERROR(EINVAL);
|
|
+ }
|
|
+
|
|
+ /* check aacplus version */
|
|
+ aacplus_cfg = aacplusEncGetCurrentConfiguration(s->aacplus_handle);
|
|
+
|
|
+ aacplus_cfg->bitRate = avctx->bit_rate;
|
|
+ aacplus_cfg->bandWidth = avctx->cutoff;
|
|
+ aacplus_cfg->outputFormat = !(avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER);
|
|
+ aacplus_cfg->inputFormat = avctx->sample_fmt == AV_SAMPLE_FMT_FLT ? AACPLUS_INPUT_FLOAT : AACPLUS_INPUT_16BIT;
|
|
+
|
|
+ if (!aacplusEncSetConfiguration(s->aacplus_handle, aacplus_cfg))
|
|
+ {
|
|
+ av_log(avctx, AV_LOG_ERROR, "libaacplus doesn't support this output format!\n");
|
|
+ return AVERROR(EINVAL);
|
|
+ }
|
|
+
|
|
+ avctx->frame_size = s->samples_input / avctx->ch_layout.nb_channels;
|
|
+ avctx->initial_padding = flag_aacplus ? INPUT_DELAY : CORE_DELAY;
|
|
+
|
|
+ ff_af_queue_init(avctx, &s->afq);
|
|
+
|
|
+ /* Set decoder specific info */
|
|
+ avctx->extradata_size = 0;
|
|
+ if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER)
|
|
+ {
|
|
+ unsigned char *buffer = NULL;
|
|
+ unsigned long decoder_specific_info_size;
|
|
+
|
|
+ if (aacplusEncGetDecoderSpecificInfo(s->aacplus_handle, &buffer, &decoder_specific_info_size) == 1)
|
|
+ {
|
|
+ avctx->extradata_size = decoder_specific_info_size;
|
|
+ avctx->extradata = av_mallocz(decoder_specific_info_size + AV_INPUT_BUFFER_PADDING_SIZE);
|
|
+
|
|
+ if (!avctx->extradata)
|
|
+ {
|
|
+ free(buffer);
|
|
+ return AVERROR(ENOMEM);
|
|
+ }
|
|
+
|
|
+ memcpy(avctx->extradata, buffer, decoder_specific_info_size);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ return -1;
|
|
+ }
|
|
+ free(buffer);
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int aacPlus_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
|
|
+ const AVFrame *frame, int *got_packet)
|
|
+{
|
|
+ aacPlusAudioContext *s = avctx->priv_data;
|
|
+ int32_t *input_buffer;
|
|
+ int ret;
|
|
+ int discard_padding;
|
|
+
|
|
+ if ((ret = ff_alloc_packet(avctx, pkt, s->max_output_bytes)) < 0)
|
|
+ return ret;
|
|
+
|
|
+ if (!frame)
|
|
+ {
|
|
+ /* Flushing */
|
|
+ ret = aacplusEncEncode(s->aacplus_handle, NULL, 0, pkt->data, pkt->size);
|
|
+ if (!ret)
|
|
+ {
|
|
+ return ret; // 0 - EOF
|
|
+ }
|
|
+ else if (ret < 0)
|
|
+ {
|
|
+ av_log(avctx, AV_LOG_ERROR, "cannot flush");
|
|
+ return AVERROR(EINVAL);
|
|
+ }
|
|
+
|
|
+ pkt->size = ret;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ /* Encoding */
|
|
+ input_buffer = (int32_t *)frame->data[0];
|
|
+ if ((ret = ff_af_queue_add(&s->afq, frame)) < 0)
|
|
+ return ret;
|
|
+
|
|
+ if ((ret = aacplusEncEncode(s->aacplus_handle, input_buffer, frame->nb_samples * avctx->ch_layout.nb_channels, pkt->data, pkt->size)) < 0)
|
|
+ {
|
|
+ av_log(avctx, AV_LOG_ERROR, "cannot encode");
|
|
+ return AVERROR(EINVAL);
|
|
+ }
|
|
+
|
|
+ pkt->size = ret;
|
|
+ }
|
|
+
|
|
+ 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);
|
|
+ }
|
|
+
|
|
+ avpkt->flags |= AV_PKT_FLAG_KEY;
|
|
+ *got_packet = 1;
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static void aacPlus_encode_flush(AVCodecContext *avctx)
|
|
+{
|
|
+ aacPlusAudioContext *s = avctx->priv_data;
|
|
+ uint8_t sink_null[32768];
|
|
+ int32_t encode_empty[32768] = {0};
|
|
+ int64_t pts, duration;
|
|
+
|
|
+ ff_af_queue_remove(&s->afq, s->afq.frame_count, &pts, &duration);
|
|
+ if (aacplusEncEncode(s->aacplus_handle, encode_empty, s->samples_input, sink_null, s->max_output_bytes) < 0)
|
|
+ av_log(avctx, AV_LOG_ERROR, "error occured when trying to flush");
|
|
+}
|
|
+
|
|
+static av_cold int aacPlus_encode_close(AVCodecContext *avctx)
|
|
+{
|
|
+ aacPlusAudioContext *s = avctx->priv_data;
|
|
+
|
|
+ if (s->aacplus_handle)
|
|
+ aacplusEncClose(s->aacplus_handle);
|
|
+
|
|
+ ff_af_queue_close(&s->afq);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static const FFCodecDefault defaults[] = {
|
|
+ {"b", "128000"},
|
|
+ {NULL}};
|
|
+
|
|
+static const AVProfile profiles[] = {
|
|
+ {AV_PROFILE_AAC_LOW, "LC"},
|
|
+ {AV_PROFILE_AAC_HE, "HE-AAC"},
|
|
+ // {FF_PROFILE_AAC_HE_V2, "HE-AACv2"},
|
|
+ {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[2] = {
|
|
+ AV_CHANNEL_LAYOUT_MONO,
|
|
+ AV_CHANNEL_LAYOUT_STEREO
|
|
+};
|
|
+
|
|
+const FFCodec ff_libaacplus_encoder = {
|
|
+ .p.name = "libaac",
|
|
+ CODEC_LONG_NAME("custom 3GPP AAC+ encoder"),
|
|
+ .p.type = AVMEDIA_TYPE_AUDIO,
|
|
+ .p.id = AV_CODEC_ID_AAC,
|
|
+ .p.capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_ENCODER_FLUSH,
|
|
+ .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE,
|
|
+ .priv_data_size = sizeof(aacPlusAudioContext),
|
|
+ .init = aacPlus_encode_init,
|
|
+ FF_CODEC_ENCODE_CB(aacPlus_encode_frame),
|
|
+ .flush = aacPlus_encode_flush,
|
|
+ .close = aacPlus_encode_close,
|
|
+ .p.sample_fmts = (const enum AVSampleFormat[]){AV_SAMPLE_FMT_S16,
|
|
+ AV_SAMPLE_FMT_FLT,
|
|
+ AV_SAMPLE_FMT_NONE},
|
|
+ .p.priv_class = &aac_enc_class,
|
|
+ .defaults = defaults,
|
|
+ .p.profiles = profiles,
|
|
+ .p.supported_samplerates = aac_sample_rates,
|
|
+ .p.ch_layouts = aac_ch_layouts,
|
|
+ .p.wrapper_name = "libaac",
|
|
+};
|
|
diff -ruN ffmpeg-7.1.1/libavcodec/Makefile ffmpeg-7.1.1-custom/libavcodec/Makefile
|
|
--- ffmpeg-7.1.1/libavcodec/Makefile 2024-09-30 06:31:47.000000000 +0700
|
|
+++ ffmpeg-7.1.1-custom/libavcodec/Makefile 2025-07-14 08:20:08.984859732 +0700
|
|
@@ -261,6 +261,7 @@
|
|
OBJS-$(CONFIG_ATRAC9_DECODER) += atrac9dec.o
|
|
OBJS-$(CONFIG_AURA_DECODER) += cyuv.o
|
|
OBJS-$(CONFIG_AURA2_DECODER) += aura.o
|
|
+OBJS-$(CONFIG_LIBAACPLUS_ENCODER) += libaacplus.o
|
|
OBJS-$(CONFIG_AV1_DECODER) += av1dec.o av1_parse.o
|
|
OBJS-$(CONFIG_AV1_CUVID_DECODER) += cuviddec.o
|
|
OBJS-$(CONFIG_AV1_MEDIACODEC_DECODER) += mediacodecdec.o
|