summaryrefslogtreecommitdiff
path: root/libavcodec/atrac3plusdec.c
diff options
context:
space:
mode:
Diffstat (limited to 'libavcodec/atrac3plusdec.c')
-rw-r--r--libavcodec/atrac3plusdec.c119
1 files changed, 67 insertions, 52 deletions
diff --git a/libavcodec/atrac3plusdec.c b/libavcodec/atrac3plusdec.c
index 17774d5657..666d1a5c01 100644
--- a/libavcodec/atrac3plusdec.c
+++ b/libavcodec/atrac3plusdec.c
@@ -3,20 +3,20 @@
*
* Copyright (c) 2010-2013 Maxim Poliakovski
*
- * This file is part of Libav.
+ * This file is part of FFmpeg.
*
- * Libav is free software; you can redistribute it and/or
+ * 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.
*
- * Libav is distributed in the hope that it will be useful,
+ * 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 Libav; if not, write to the Free Software
+ * License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@@ -39,16 +39,15 @@
#include "libavutil/channel_layout.h"
#include "libavutil/float_dsp.h"
-
#include "avcodec.h"
-#include "bitstream.h"
+#include "get_bits.h"
#include "internal.h"
#include "atrac.h"
#include "atrac3plus.h"
typedef struct ATRAC3PContext {
- BitstreamContext bc;
- AVFloatDSPContext fdsp;
+ GetBitContext gb;
+ AVFloatDSPContext *fdsp;
DECLARE_ALIGNED(32, float, samples)[2][ATRAC3P_FRAME_SAMPLES]; ///< quantized MDCT spectrum
DECLARE_ALIGNED(32, float, mdct_buf)[2][ATRAC3P_FRAME_SAMPLES]; ///< output of the IMDCT
@@ -68,7 +67,13 @@ typedef struct ATRAC3PContext {
static av_cold int atrac3p_decode_close(AVCodecContext *avctx)
{
- av_free(((ATRAC3PContext *)(avctx->priv_data))->ch_units);
+ ATRAC3PContext *ctx = avctx->priv_data;
+
+ av_freep(&ctx->ch_units);
+ av_freep(&ctx->fdsp);
+
+ ff_mdct_end(&ctx->mdct_ctx);
+ ff_mdct_end(&ctx->ipqf_dct_ctx);
return 0;
}
@@ -149,7 +154,7 @@ static av_cold int atrac3p_decode_init(AVCodecContext *avctx)
return AVERROR(EINVAL);
}
- avpriv_float_dsp_init(&ctx->fdsp, avctx->flags & AV_CODEC_FLAG_BITEXACT);
+ ff_atrac3p_init_vlcs();
/* initialize IPQF */
ff_mdct_init(&ctx->ipqf_dct_ctx, 5, 1, 32.0 / 32768.0);
@@ -165,9 +170,10 @@ static av_cold int atrac3p_decode_init(AVCodecContext *avctx)
ctx->my_channel_layout = avctx->channel_layout;
- ctx->ch_units = av_mallocz(sizeof(*ctx->ch_units) *
- ctx->num_channel_blocks);
- if (!ctx->ch_units) {
+ ctx->ch_units = av_mallocz_array(ctx->num_channel_blocks, sizeof(*ctx->ch_units));
+ ctx->fdsp = avpriv_float_dsp_alloc(avctx->flags & AV_CODEC_FLAG_BITEXACT);
+
+ if (!ctx->ch_units || !ctx->fdsp) {
atrac3p_decode_close(avctx);
return AVERROR(ENOMEM);
}
@@ -192,7 +198,7 @@ static av_cold int atrac3p_decode_init(AVCodecContext *avctx)
return 0;
}
-static void decode_residual_spectrum(Atrac3pChanUnitCtx *ctx,
+static void decode_residual_spectrum(ATRAC3PContext *ctx, Atrac3pChanUnitCtx *ch_unit,
float out[2][ATRAC3P_FRAME_SAMPLES],
int num_channels,
AVCodecContext *avctx)
@@ -203,17 +209,17 @@ static void decode_residual_spectrum(Atrac3pChanUnitCtx *ctx,
/* calculate RNG table index for each subband */
int sb_RNG_index[ATRAC3P_SUBBANDS] = { 0 };
- if (ctx->mute_flag) {
+ if (ch_unit->mute_flag) {
for (ch = 0; ch < num_channels; ch++)
memset(out[ch], 0, ATRAC3P_FRAME_SAMPLES * sizeof(*out[ch]));
return;
}
- for (qu = 0, RNG_index = 0; qu < ctx->used_quant_units; qu++)
- RNG_index += ctx->channels[0].qu_sf_idx[qu] +
- ctx->channels[1].qu_sf_idx[qu];
+ for (qu = 0, RNG_index = 0; qu < ch_unit->used_quant_units; qu++)
+ RNG_index += ch_unit->channels[0].qu_sf_idx[qu] +
+ ch_unit->channels[1].qu_sf_idx[qu];
- for (sb = 0; sb < ctx->num_coded_subbands; sb++, RNG_index += 128)
+ for (sb = 0; sb < ch_unit->num_coded_subbands; sb++, RNG_index += 128)
sb_RNG_index[sb] = RNG_index & 0x3FC;
/* inverse quant and power compensation */
@@ -221,35 +227,35 @@ static void decode_residual_spectrum(Atrac3pChanUnitCtx *ctx,
/* clear channel's residual spectrum */
memset(out[ch], 0, ATRAC3P_FRAME_SAMPLES * sizeof(*out[ch]));
- for (qu = 0; qu < ctx->used_quant_units; qu++) {
- src = &ctx->channels[ch].spectrum[ff_atrac3p_qu_to_spec_pos[qu]];
+ for (qu = 0; qu < ch_unit->used_quant_units; qu++) {
+ src = &ch_unit->channels[ch].spectrum[ff_atrac3p_qu_to_spec_pos[qu]];
dst = &out[ch][ff_atrac3p_qu_to_spec_pos[qu]];
nspeclines = ff_atrac3p_qu_to_spec_pos[qu + 1] -
ff_atrac3p_qu_to_spec_pos[qu];
- if (ctx->channels[ch].qu_wordlen[qu] > 0) {
- q = ff_atrac3p_sf_tab[ctx->channels[ch].qu_sf_idx[qu]] *
- ff_atrac3p_mant_tab[ctx->channels[ch].qu_wordlen[qu]];
+ if (ch_unit->channels[ch].qu_wordlen[qu] > 0) {
+ q = ff_atrac3p_sf_tab[ch_unit->channels[ch].qu_sf_idx[qu]] *
+ ff_atrac3p_mant_tab[ch_unit->channels[ch].qu_wordlen[qu]];
for (i = 0; i < nspeclines; i++)
dst[i] = src[i] * q;
}
}
- for (sb = 0; sb < ctx->num_coded_subbands; sb++)
- ff_atrac3p_power_compensation(ctx, ch, &out[ch][0],
+ for (sb = 0; sb < ch_unit->num_coded_subbands; sb++)
+ ff_atrac3p_power_compensation(ch_unit, ctx->fdsp, ch, &out[ch][0],
sb_RNG_index[sb], sb);
}
- if (ctx->unit_type == CH_UNIT_STEREO) {
- for (sb = 0; sb < ctx->num_coded_subbands; sb++) {
- if (ctx->swap_channels[sb]) {
+ if (ch_unit->unit_type == CH_UNIT_STEREO) {
+ for (sb = 0; sb < ch_unit->num_coded_subbands; sb++) {
+ if (ch_unit->swap_channels[sb]) {
for (i = 0; i < ATRAC3P_SUBBAND_SAMPLES; i++)
FFSWAP(float, out[0][sb * ATRAC3P_SUBBAND_SAMPLES + i],
out[1][sb * ATRAC3P_SUBBAND_SAMPLES + i]);
}
/* flip coefficients' sign if requested */
- if (ctx->negate_coeffs[sb])
+ if (ch_unit->negate_coeffs[sb])
for (i = 0; i < ATRAC3P_SUBBAND_SAMPLES; i++)
out[1][sb * ATRAC3P_SUBBAND_SAMPLES + i] = -(out[1][sb * ATRAC3P_SUBBAND_SAMPLES + i]);
}
@@ -264,7 +270,7 @@ static void reconstruct_frame(ATRAC3PContext *ctx, Atrac3pChanUnitCtx *ch_unit,
for (ch = 0; ch < num_channels; ch++) {
for (sb = 0; sb < ch_unit->num_subbands; sb++) {
/* inverse transform and windowing */
- ff_atrac3p_imdct(&ctx->fdsp, &ctx->mdct_ctx,
+ ff_atrac3p_imdct(ctx->fdsp, &ctx->mdct_ctx,
&ctx->samples[ch][sb * ATRAC3P_SUBBAND_SAMPLES],
&ctx->mdct_buf[ch][sb * ATRAC3P_SUBBAND_SAMPLES],
(ch_unit->channels[ch].wnd_shape_prev[sb] << 1) +
@@ -298,7 +304,7 @@ static void reconstruct_frame(ATRAC3PContext *ctx, Atrac3pChanUnitCtx *ch_unit,
for (sb = 0; sb < ch_unit->num_subbands; sb++)
if (ch_unit->channels[ch].tones_info[sb].num_wavs ||
ch_unit->channels[ch].tones_info_prev[sb].num_wavs) {
- ff_atrac3p_generate_tones(ch_unit, &ctx->fdsp, ch, sb,
+ ff_atrac3p_generate_tones(ch_unit, ctx->fdsp, ch, sb,
&ctx->time_buf[ch][sb * 128]);
}
}
@@ -330,21 +336,19 @@ static int atrac3p_decode_frame(AVCodecContext *avctx, void *data,
float **samples_p = (float **)frame->extended_data;
frame->nb_samples = ATRAC3P_FRAME_SAMPLES;
- if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) {
- av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+ if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
return ret;
- }
- if ((ret = bitstream_init8(&ctx->bc, avpkt->data, avpkt->size)) < 0)
+ if ((ret = init_get_bits8(&ctx->gb, avpkt->data, avpkt->size)) < 0)
return ret;
- if (bitstream_read_bit(&ctx->bc)) {
+ if (get_bits1(&ctx->gb)) {
av_log(avctx, AV_LOG_ERROR, "Invalid start bit!\n");
return AVERROR_INVALIDDATA;
}
- while (bitstream_bits_left(&ctx->bc) >= 2 &&
- (ch_unit_id = bitstream_read(&ctx->bc, 2)) != CH_UNIT_TERMINATOR) {
+ while (get_bits_left(&ctx->gb) >= 2 &&
+ (ch_unit_id = get_bits(&ctx->gb, 2)) != CH_UNIT_TERMINATOR) {
if (ch_unit_id == CH_UNIT_EXTENSION) {
avpriv_report_missing_feature(avctx, "Channel unit extension");
return AVERROR_PATCHWELCOME;
@@ -359,13 +363,13 @@ static int atrac3p_decode_frame(AVCodecContext *avctx, void *data,
ctx->ch_units[ch_block].unit_type = ch_unit_id;
channels_to_process = ch_unit_id + 1;
- if ((ret = ff_atrac3p_decode_channel_unit(&ctx->bc,
+ if ((ret = ff_atrac3p_decode_channel_unit(&ctx->gb,
&ctx->ch_units[ch_block],
channels_to_process,
avctx)) < 0)
return ret;
- decode_residual_spectrum(&ctx->ch_units[ch_block], ctx->samples,
+ decode_residual_spectrum(ctx, &ctx->ch_units[ch_block], ctx->samples,
channels_to_process, avctx);
reconstruct_frame(ctx, &ctx->ch_units[ch_block],
channels_to_process, avctx);
@@ -380,18 +384,29 @@ static int atrac3p_decode_frame(AVCodecContext *avctx, void *data,
*got_frame_ptr = 1;
- return avctx->block_align;
+ return avctx->codec_id == AV_CODEC_ID_ATRAC3P ? FFMIN(avctx->block_align, avpkt->size) : avpkt->size;
}
AVCodec ff_atrac3p_decoder = {
- .name = "atrac3plus",
- .long_name = NULL_IF_CONFIG_SMALL("ATRAC3+ (Adaptive TRansform Acoustic Coding 3+)"),
- .type = AVMEDIA_TYPE_AUDIO,
- .id = AV_CODEC_ID_ATRAC3P,
- .capabilities = AV_CODEC_CAP_DR1,
- .priv_data_size = sizeof(ATRAC3PContext),
- .init = atrac3p_decode_init,
- .init_static_data = ff_atrac3p_init_vlcs,
- .close = atrac3p_decode_close,
- .decode = atrac3p_decode_frame,
+ .name = "atrac3plus",
+ .long_name = NULL_IF_CONFIG_SMALL("ATRAC3+ (Adaptive TRansform Acoustic Coding 3+)"),
+ .type = AVMEDIA_TYPE_AUDIO,
+ .id = AV_CODEC_ID_ATRAC3P,
+ .capabilities = AV_CODEC_CAP_DR1,
+ .priv_data_size = sizeof(ATRAC3PContext),
+ .init = atrac3p_decode_init,
+ .close = atrac3p_decode_close,
+ .decode = atrac3p_decode_frame,
+};
+
+AVCodec ff_atrac3pal_decoder = {
+ .name = "atrac3plusal",
+ .long_name = NULL_IF_CONFIG_SMALL("ATRAC3+ AL (Adaptive TRansform Acoustic Coding 3+ Advanced Lossless)"),
+ .type = AVMEDIA_TYPE_AUDIO,
+ .id = AV_CODEC_ID_ATRAC3PAL,
+ .capabilities = AV_CODEC_CAP_DR1,
+ .priv_data_size = sizeof(ATRAC3PContext),
+ .init = atrac3p_decode_init,
+ .close = atrac3p_decode_close,
+ .decode = atrac3p_decode_frame,
};