1
0
mirror of https://github.com/FFmpeg/FFmpeg.git synced 2025-08-04 22:03:09 +02:00

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>
This commit is contained in:
Andreas Rheinhardt
2025-04-10 21:07:00 +02:00
parent 13a0d0ade1
commit db75955d60
4 changed files with 134 additions and 156 deletions

View File

@ -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

View File

@ -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

View File

@ -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,
};

View File

@ -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,
};