#include "libavutil/attributes.h"
#include "libavutil/float_dsp.h"
#include "libavutil/libm.h"
+#include "libavutil/mem_internal.h"
+#include "libavutil/thread.h"
+
#include "avcodec.h"
#include "bytestream.h"
#include "fft.h"
#define SAMPLES_PER_FRAME 1024
#define MDCT_SIZE 512
+#define ATRAC3_VLC_BITS 8
+
typedef struct GainBlock {
AtracGainInfo g_block[4];
} GainBlock;
AtracGCContext gainc_ctx;
FFTContext mdct_ctx;
- AVFloatDSPContext *fdsp;
+ void (*vector_fmul)(float *dst, const float *src0, const float *src1,
+ int len);
} ATRAC3Context;
static DECLARE_ALIGNED(32, float, mdct_window)[MDCT_SIZE];
-static VLC_TYPE atrac3_vlc_table[4096][2];
+static VLC_TYPE atrac3_vlc_table[7 * 1 << ATRAC3_VLC_BITS][2];
static VLC spectral_coeff_tab[7];
/**
q->mdct_ctx.imdct_calc(&q->mdct_ctx, output, input);
/* Perform windowing on the output. */
- q->fdsp->vector_fmul(output, output, mdct_window, MDCT_SIZE);
+ q->vector_fmul(output, output, mdct_window, MDCT_SIZE);
}
/*
av_freep(&q->units);
av_freep(&q->decoded_bytes_buffer);
- av_freep(&q->fdsp);
ff_mdct_end(&q->mdct_ctx);
/* variable length coding (VLC) */
if (selector != 1) {
for (i = 0; i < num_codes; i++) {
- huff_symb = get_vlc2(gb, spectral_coeff_tab[selector-1].table,
- spectral_coeff_tab[selector-1].bits, 3);
- huff_symb += 1;
- code = huff_symb >> 1;
- if (huff_symb & 1)
- code = -code;
- mantissas[i] = code;
+ mantissas[i] = get_vlc2(gb, spectral_coeff_tab[selector-1].table,
+ ATRAC3_VLC_BITS, 1);
}
} else {
for (i = 0; i < num_codes; i++) {
huff_symb = get_vlc2(gb, spectral_coeff_tab[selector - 1].table,
- spectral_coeff_tab[selector - 1].bits, 3);
+ ATRAC3_VLC_BITS, 1);
mantissas[i * 2 ] = mantissa_vlc_tab[huff_symb * 2 ];
mantissas[i * 2 + 1] = mantissa_vlc_tab[huff_symb * 2 + 1];
}
static av_cold void atrac3_init_static_data(void)
{
+ VLC_TYPE (*table)[2] = atrac3_vlc_table;
+ const uint8_t (*hufftabs)[2] = atrac3_hufftabs;
int i;
init_imdct_window();
/* Initialize the VLC tables. */
for (i = 0; i < 7; i++) {
- spectral_coeff_tab[i].table = &atrac3_vlc_table[atrac3_vlc_offs[i]];
- spectral_coeff_tab[i].table_allocated = atrac3_vlc_offs[i + 1] -
- atrac3_vlc_offs[i ];
- init_vlc(&spectral_coeff_tab[i], 9, huff_tab_sizes[i],
- huff_bits[i], 1, 1,
- huff_codes[i], 1, 1, INIT_VLC_USE_NEW_STATIC);
+ spectral_coeff_tab[i].table = table;
+ spectral_coeff_tab[i].table_allocated = 256;
+ ff_init_vlc_from_lengths(&spectral_coeff_tab[i], ATRAC3_VLC_BITS, huff_tab_sizes[i],
+ &hufftabs[0][1], 2,
+ &hufftabs[0][0], 2, 1,
+ -31, INIT_VLC_USE_NEW_STATIC, NULL);
+ hufftabs += huff_tab_sizes[i];
+ table += 256;
}
}
static av_cold int atrac3_decode_init(AVCodecContext *avctx)
{
- static int static_init_done;
+ static AVOnce init_static_once = AV_ONCE_INIT;
int i, js_pair, ret;
int version, delay, samples_per_frame, frame_factor;
const uint8_t *edata_ptr = avctx->extradata;
ATRAC3Context *q = avctx->priv_data;
+ AVFloatDSPContext *fdsp;
if (avctx->channels < MIN_CHANNELS || avctx->channels > MAX_CHANNELS) {
av_log(avctx, AV_LOG_ERROR, "Channel configuration error!\n");
return AVERROR(EINVAL);
}
- if (!static_init_done)
- atrac3_init_static_data();
- static_init_done = 1;
-
/* Take care of the codec-specific extradata. */
if (avctx->codec_id == AV_CODEC_ID_ATRAC3AL) {
version = 4;
return AVERROR_INVALIDDATA;
}
- if (avctx->block_align >= UINT_MAX / 2)
+ if (avctx->block_align > 4096 || avctx->block_align <= 0)
return AVERROR(EINVAL);
q->decoded_bytes_buffer = av_mallocz(FFALIGN(avctx->block_align, 4) +
/* initialize the MDCT transform */
if ((ret = ff_mdct_init(&q->mdct_ctx, 9, 1, 1.0 / 32768)) < 0) {
av_log(avctx, AV_LOG_ERROR, "Error initializing MDCT\n");
- av_freep(&q->decoded_bytes_buffer);
return ret;
}
}
ff_atrac_init_gain_compensation(&q->gainc_ctx, 4, 3);
- q->fdsp = avpriv_float_dsp_alloc(avctx->flags & AV_CODEC_FLAG_BITEXACT);
+ fdsp = avpriv_float_dsp_alloc(avctx->flags & AV_CODEC_FLAG_BITEXACT);
+ if (!fdsp)
+ return AVERROR(ENOMEM);
+ q->vector_fmul = fdsp->vector_fmul;
+ av_free(fdsp);
q->units = av_mallocz_array(avctx->channels, sizeof(*q->units));
- if (!q->units || !q->fdsp) {
- atrac3_decode_close(avctx);
+ if (!q->units)
return AVERROR(ENOMEM);
- }
+
+ ff_thread_once(&init_static_once, atrac3_init_static_data);
return 0;
}
-AVCodec ff_atrac3_decoder = {
+const AVCodec ff_atrac3_decoder = {
.name = "atrac3",
.long_name = NULL_IF_CONFIG_SMALL("ATRAC3 (Adaptive TRansform Acoustic Coding 3)"),
.type = AVMEDIA_TYPE_AUDIO,
.capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1,
.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP,
AV_SAMPLE_FMT_NONE },
+ .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
};
-AVCodec ff_atrac3al_decoder = {
+const AVCodec ff_atrac3al_decoder = {
.name = "atrac3al",
.long_name = NULL_IF_CONFIG_SMALL("ATRAC3 AL (Adaptive TRansform Acoustic Coding 3 Advanced Lossless)"),
.type = AVMEDIA_TYPE_AUDIO,
.capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1,
.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP,
AV_SAMPLE_FMT_NONE },
+ .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
};