From efa54c902f9413eee080dec3ec8cdc480c9ea6ce Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Date: Thu, 10 Apr 2025 21:07:00 +0200 Subject: [PATCH 10/15] avcodec/mpegaudioenc_{fixed,float}: Merge encoders Most of the encoders is the same. So deduplicate them. This reduces code size from 22410B to 12637B here. The data in mpegaudiotab.h is also automatically deduplicated. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavcodec/Makefile | 4 +- ...mpegaudioenc_template.c => mpegaudioenc.c} | 207 +++++++++++------- libavcodec/mpegaudioenc_fixed.c | 39 ---- libavcodec/mpegaudioenc_float.c | 40 ---- 4 files changed, 134 insertions(+), 156 deletions(-) rename libavcodec/{mpegaudioenc_template.c => mpegaudioenc.c} (84%) delete mode 100644 libavcodec/mpegaudioenc_fixed.c delete mode 100644 libavcodec/mpegaudioenc_float.c diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 3c3ac640e0..98501f9797 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -529,10 +529,10 @@ OBJS-$(CONFIG_MOVTEXT_ENCODER) += movtextenc.o ass_split.o OBJS-$(CONFIG_MP1_DECODER) += mpegaudiodec_fixed.o OBJS-$(CONFIG_MP1FLOAT_DECODER) += mpegaudiodec_float.o OBJS-$(CONFIG_MP2_DECODER) += mpegaudiodec_fixed.o -OBJS-$(CONFIG_MP2_ENCODER) += mpegaudioenc_float.o mpegaudio.o \ +OBJS-$(CONFIG_MP2_ENCODER) += mpegaudioenc.o mpegaudio.o \ mpegaudiodata.o mpegaudiodsp_data.o \ mpegaudiotabs.o -OBJS-$(CONFIG_MP2FIXED_ENCODER) += mpegaudioenc_fixed.o mpegaudio.o \ +OBJS-$(CONFIG_MP2FIXED_ENCODER) += mpegaudioenc.o mpegaudio.o \ mpegaudiodata.o mpegaudiodsp_data.o \ mpegaudiotabs.o OBJS-$(CONFIG_MP2FLOAT_DECODER) += mpegaudiodec_float.o diff --git a/libavcodec/mpegaudioenc_template.c b/libavcodec/mpegaudioenc.c similarity index 84% rename from libavcodec/mpegaudioenc_template.c rename to libavcodec/mpegaudioenc.c index 12f5c7b9cd..35347d386c 100644 --- a/libavcodec/mpegaudioenc_template.c +++ b/libavcodec/mpegaudioenc.c @@ -24,10 +24,14 @@ * The simplest mpeg audio layer 2 encoder. */ +#include "config.h" +#include "config_components.h" + #include "libavutil/avassert.h" #include "libavutil/channel_layout.h" #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" #include "put_bits.h" @@ -52,6 +56,7 @@ typedef struct MpegAudioContext { int bitrate_index; /* bit rate */ int freq_index; int frame_size; /* frame size, in bits, without padding */ + int is_fixed; /* padding computation */ int frame_frac, frame_frac_incr, do_padding; short samples_buf[MPA_MAX_CHANNELS][SAMPLES_BUF_SIZE]; /* buffer for filter */ @@ -65,15 +70,18 @@ typedef struct MpegAudioContext { int16_t filter_bank[512]; int scale_factor_table[64]; unsigned char scale_diff_table[128]; -#if USE_FLOATS - float scale_factor_inv_table[64]; -#else - int8_t scale_factor_shift[64]; - unsigned short scale_factor_mult[64]; -#endif + union { + float scale_factor_inv_table[64]; + struct { + int8_t scale_factor_shift[64]; + unsigned short scale_factor_mult[64]; + }; + }; unsigned short total_quant_bits[17]; /* total number of bits per allocation group */ } MpegAudioContext; +#define IS_FIXED(s) (CONFIG_MP2_ENCODER && CONFIG_MP2FIXED_ENCODER ? (s)->is_fixed : CONFIG_MP2FIXED_ENCODER) + static av_cold int MPA_encode_init(AVCodecContext *avctx) { MpegAudioContext *s = avctx->priv_data; @@ -157,13 +165,13 @@ static av_cold int MPA_encode_init(AVCodecContext *avctx) if (v <= 0) v = 1; s->scale_factor_table[i] = v; -#if USE_FLOATS - s->scale_factor_inv_table[i] = exp2(-(3 - i) / 3.0) / (float)(1 << 20); -#else + if (IS_FIXED(s)) { #define P 15 - s->scale_factor_shift[i] = 21 - P - (i / 3); - s->scale_factor_mult[i] = (1 << P) * exp2((i % 3) / 3.0); -#endif + s->scale_factor_shift[i] = 21 - P - (i / 3); + s->scale_factor_mult[i] = (1 << P) * exp2((i % 3) / 3.0); + } else { + s->scale_factor_inv_table[i] = exp2(-(3 - i) / 3.0) / (float)(1 << 20); + } } for(i=0;i<128;i++) { v = i - 64; @@ -592,6 +600,70 @@ static void compute_bit_allocation(MpegAudioContext *s, av_assert0(*padding >= 0); } +/// Quantization & write sub band samples +static av_always_inline void encode_subbands(MpegAudioContext *const s, + PutBitContext *const p, + const uint8_t bit_alloc[MPA_MAX_CHANNELS][SBLIMIT], + int is_fixed) +{ + for (int k = 0; k < 3; ++k) { + for (int l = 0; l < 12; l += 3) { + for (int i = 0, j = 0; i < s->sblimit; ++i) { + const int bit_alloc_bits = s->alloc_table[j]; + for (int ch = 0; ch < s->nb_channels; ++ch) { + const int b = bit_alloc[ch][i]; + if (b) { + /* we encode 3 sub band samples of the same sub band at a time */ + const int qindex = s->alloc_table[j + b]; + const int steps = ff_mpa_quant_steps[qindex]; + int q[3]; + + for (int m = 0; m < 3; ++m) { + const int sample = s->sb_samples[ch][k][l + m][i]; + /* divide by scale factor */ + if (!is_fixed) { + float a = (float)sample * s->scale_factor_inv_table[s->scale_factors[ch][i][k]]; + q[m] = (int)((a + 1.0) * steps * 0.5); + } else { + const int e = s->scale_factors[ch][i][k]; + const int shift = s->scale_factor_shift[e]; + const int mult = s->scale_factor_mult[e]; + int q1; + + /* normalize to P bits */ + if (shift < 0) + q1 = sample * (1 << -shift); + else + q1 = sample >> shift; + q1 = (q1 * mult) >> P; + q1 += 1 << P; + if (q1 < 0) + q1 = 0; + q[m] = (q1 * (unsigned)steps) >> (P + 1); + } + if (q[m] >= steps) + q[m] = steps - 1; + av_assert2(q[m] >= 0 && q[m] < steps); + } + const int bits = ff_mpa_quant_bits[qindex]; + if (bits < 0) { + /* group the 3 values to save bits */ + put_bits(p, -bits, + q[0] + steps * (q[1] + steps * q[2])); + } else { + put_bits(p, bits, q[0]); + put_bits(p, bits, q[1]); + put_bits(p, bits, q[2]); + } + } + } + /* next subband in alloc table */ + j += 1 << bit_alloc_bits; + } + } + } +} + /* * Output the MPEG audio layer 2 frame. Note how the code is small * compared to other encoders :-) @@ -600,9 +672,8 @@ static void encode_frame(MpegAudioContext *s, unsigned char bit_alloc[MPA_MAX_CHANNELS][SBLIMIT], int padding) { - int i, j, k, l, bit_alloc_bits, b, ch; + int i, j, bit_alloc_bits, ch; unsigned char *sf; - int q[3]; PutBitContext *p = &s->pb; /* header */ @@ -663,69 +734,14 @@ static void encode_frame(MpegAudioContext *s, } } - /* quantization & write sub band samples */ - - for(k=0;k<3;k++) { - for(l=0;l<12;l+=3) { - j = 0; - for(i=0;i<s->sblimit;i++) { - bit_alloc_bits = s->alloc_table[j]; - for(ch=0;ch<s->nb_channels;ch++) { - b = bit_alloc[ch][i]; - if (b) { - int qindex, steps, m, sample, bits; - /* we encode 3 sub band samples of the same sub band at a time */ - qindex = s->alloc_table[j+b]; - steps = ff_mpa_quant_steps[qindex]; - for(m=0;m<3;m++) { - sample = s->sb_samples[ch][k][l + m][i]; - /* divide by scale factor */ -#if USE_FLOATS - { - float a; - a = (float)sample * s->scale_factor_inv_table[s->scale_factors[ch][i][k]]; - q[m] = (int)((a + 1.0) * steps * 0.5); - } +#if CONFIG_SMALL + encode_subbands(s, p, bit_alloc, IS_FIXED(s)); #else - { - int q1, e, shift, mult; - e = s->scale_factors[ch][i][k]; - shift = s->scale_factor_shift[e]; - mult = s->scale_factor_mult[e]; - - /* normalize to P bits */ - if (shift < 0) - q1 = sample * (1 << -shift); - else - q1 = sample >> shift; - q1 = (q1 * mult) >> P; - q1 += 1 << P; - if (q1 < 0) - q1 = 0; - q[m] = (q1 * (unsigned)steps) >> (P + 1); - } + if (IS_FIXED(s)) + encode_subbands(s, p, bit_alloc, 1); + else + encode_subbands(s, p, bit_alloc, 0); #endif - if (q[m] >= steps) - q[m] = steps - 1; - av_assert2(q[m] >= 0 && q[m] < steps); - } - bits = ff_mpa_quant_bits[qindex]; - if (bits < 0) { - /* group the 3 values to save bits */ - put_bits(p, -bits, - q[0] + steps * (q[1] + steps * q[2])); - } else { - put_bits(p, bits, q[0]); - put_bits(p, bits, q[1]); - put_bits(p, bits, q[2]); - } - } - } - /* next subband in alloc table */ - j += 1 << bit_alloc_bits; - } - } - } /* padding */ for(i=0;i<padding;i++) @@ -777,3 +793,44 @@ static const FFCodecDefault mp2_defaults[] = { { NULL }, }; +#if CONFIG_MP2_ENCODER +const FFCodec ff_mp2_encoder = { + .p.name = "mp2", + CODEC_LONG_NAME("MP2 (MPEG audio layer 2)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_MP2, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, + .priv_data_size = sizeof(MpegAudioContext), + .init = MPA_encode_init, + FF_CODEC_ENCODE_CB(MPA_encode_frame), + CODEC_SAMPLEFMTS(AV_SAMPLE_FMT_S16), + CODEC_SAMPLERATES(44100, 48000, 32000, 22050, 24000, 16000), + CODEC_CH_LAYOUTS(AV_CHANNEL_LAYOUT_MONO, AV_CHANNEL_LAYOUT_STEREO), + .defaults = mp2_defaults, +}; +#endif + +#if CONFIG_MP2FIXED_ENCODER +static av_cold int mpa_fixed_encode_init(AVCodecContext *avctx) +{ + MpegAudioContext *s = avctx->priv_data; + + s->is_fixed = 1; + return MPA_encode_init(avctx); +} + +const FFCodec ff_mp2fixed_encoder = { + .p.name = "mp2fixed", + CODEC_LONG_NAME("MP2 fixed point (MPEG audio layer 2)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_MP2, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, + .priv_data_size = sizeof(MpegAudioContext), + .init = mpa_fixed_encode_init, + FF_CODEC_ENCODE_CB(MPA_encode_frame), + CODEC_SAMPLEFMTS(AV_SAMPLE_FMT_S16), + CODEC_SAMPLERATES(44100, 48000, 32000, 22050, 24000, 16000), + CODEC_CH_LAYOUTS(AV_CHANNEL_LAYOUT_MONO, AV_CHANNEL_LAYOUT_STEREO), + .defaults = mp2_defaults, +}; +#endif diff --git a/libavcodec/mpegaudioenc_fixed.c b/libavcodec/mpegaudioenc_fixed.c deleted file mode 100644 index a9faa7e059..0000000000 --- a/libavcodec/mpegaudioenc_fixed.c +++ /dev/null @@ -1,39 +0,0 @@ -/* - * The simplest mpeg audio layer 2 encoder - * Copyright (c) 2000, 2001 Fabrice Bellard - * - * 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 - */ - -#include "libavutil/channel_layout.h" -#include "codec_internal.h" -#include "mpegaudioenc_template.c" - -const FFCodec ff_mp2fixed_encoder = { - .p.name = "mp2fixed", - CODEC_LONG_NAME("MP2 fixed point (MPEG audio layer 2)"), - .p.type = AVMEDIA_TYPE_AUDIO, - .p.id = AV_CODEC_ID_MP2, - .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, - .priv_data_size = sizeof(MpegAudioContext), - .init = MPA_encode_init, - FF_CODEC_ENCODE_CB(MPA_encode_frame), - CODEC_SAMPLEFMTS(AV_SAMPLE_FMT_S16), - CODEC_SAMPLERATES(44100, 48000, 32000, 22050, 24000, 16000), - CODEC_CH_LAYOUTS(AV_CHANNEL_LAYOUT_MONO, AV_CHANNEL_LAYOUT_STEREO), - .defaults = mp2_defaults, -}; diff --git a/libavcodec/mpegaudioenc_float.c b/libavcodec/mpegaudioenc_float.c deleted file mode 100644 index 5ff67960b5..0000000000 --- a/libavcodec/mpegaudioenc_float.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - * The simplest mpeg audio layer 2 encoder - * Copyright (c) 2000, 2001 Fabrice Bellard - * - * 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 - */ - -#include "libavutil/channel_layout.h" -#define USE_FLOATS 1 -#include "codec_internal.h" -#include "mpegaudioenc_template.c" - -const FFCodec ff_mp2_encoder = { - .p.name = "mp2", - CODEC_LONG_NAME("MP2 (MPEG audio layer 2)"), - .p.type = AVMEDIA_TYPE_AUDIO, - .p.id = AV_CODEC_ID_MP2, - .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, - .priv_data_size = sizeof(MpegAudioContext), - .init = MPA_encode_init, - FF_CODEC_ENCODE_CB(MPA_encode_frame), - CODEC_SAMPLEFMTS(AV_SAMPLE_FMT_S16), - CODEC_SAMPLERATES(44100, 48000, 32000, 22050, 24000, 16000), - CODEC_CH_LAYOUTS(AV_CHANNEL_LAYOUT_MONO, AV_CHANNEL_LAYOUT_STEREO), - .defaults = mp2_defaults, -}; -- 2.45.2