[FFmpeg-cvslog] avcodec/mpegaudioenc_{fixed,float}: Merge encoders
Andreas Rheinhardt
git at videolan.org
Mon Apr 14 00:18:26 EEST 2025
ffmpeg | branch: master | Andreas Rheinhardt <andreas.rheinhardt at outlook.com> | Thu Apr 10 21:07:00 2025 +0200| [db75955d6023ead1bc306c9b0969054efa29c3e7] | committer: Andreas Rheinhardt
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 at outlook.com>
> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=db75955d6023ead1bc306c9b0969054efa29c3e7
---
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(-)
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 5ec2b7f5ad..7bd1dbec9a 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,
-};
More information about the ffmpeg-cvslog
mailing list