* subframe in order to reconstruct the output samples.
*/
+#include <inttypes.h>
+
#include "libavutil/float_dsp.h"
#include "libavutil/intfloat.h"
#include "libavutil/intreadwrite.h"
#define WMAPRO_BLOCK_MIN_BITS 6 ///< log2 of min block size
#define WMAPRO_BLOCK_MAX_BITS 13 ///< log2 of max block size
+#define WMAPRO_BLOCK_MIN_SIZE (1 << WMAPRO_BLOCK_MIN_BITS) ///< minimum block size
#define WMAPRO_BLOCK_MAX_SIZE (1 << WMAPRO_BLOCK_MAX_BITS) ///< maximum block size
#define WMAPRO_BLOCK_SIZES (WMAPRO_BLOCK_MAX_BITS - WMAPRO_BLOCK_MIN_BITS + 1) ///< possible block sizes
static VLC vec2_vlc; ///< 2 coefficients per symbol
static VLC vec1_vlc; ///< 1 coefficient per symbol
static VLC coef_vlc[2]; ///< coefficient run length vlc codes
-static float sin64[33]; ///< sinus table for decorrelation
+static float sin64[33]; ///< sine table for decorrelation
/**
* @brief frame specific decoder context for a single channel
*/
-typedef struct {
+typedef struct WMAProChannelCtx {
int16_t prev_block_len; ///< length of the previous block
uint8_t transmit_coefs;
uint8_t num_subframes;
/**
* @brief channel group for channel transformations
*/
-typedef struct {
+typedef struct WMAProChannelGrp {
uint8_t num_channels; ///< number of channels in the group
int8_t transform; ///< transform on / off
int8_t transform_band[MAX_BANDS]; ///< controls if the transform is enabled for a certain band
AVCodecContext* avctx; ///< codec context for av_log
AVFloatDSPContext fdsp;
uint8_t frame_data[MAX_FRAMESIZE +
- FF_INPUT_BUFFER_PADDING_SIZE];///< compressed frame data
+ AV_INPUT_BUFFER_PADDING_SIZE];///< compressed frame data
PutBitContext pb; ///< context for filling the frame_data buffer
FFTContext mdct_ctx[WMAPRO_BLOCK_SIZES]; ///< MDCT context per block size
DECLARE_ALIGNED(32, float, tmp)[WMAPRO_BLOCK_MAX_SIZE]; ///< IMDCT output buffer
static av_cold void dump_context(WMAProDecodeCtx *s)
{
#define PRINT(a, b) av_log(s->avctx, AV_LOG_DEBUG, " %s = %d\n", a, b);
-#define PRINT_HEX(a, b) av_log(s->avctx, AV_LOG_DEBUG, " %s = %x\n", a, b);
+#define PRINT_HEX(a, b) av_log(s->avctx, AV_LOG_DEBUG, " %s = %"PRIx32"\n", a, b);
PRINT("ed sample bit depth", s->bits_per_sample);
PRINT_HEX("ed decode flags", s->decode_flags);
int log2_max_num_subframes;
int num_possible_block_sizes;
+ if (!avctx->block_align) {
+ av_log(avctx, AV_LOG_ERROR, "block_align is not set\n");
+ return AVERROR(EINVAL);
+ }
+
s->avctx = avctx;
- avpriv_float_dsp_init(&s->fdsp, avctx->flags & CODEC_FLAG_BITEXACT);
+ avpriv_float_dsp_init(&s->fdsp, avctx->flags & AV_CODEC_FLAG_BITEXACT);
init_put_bits(&s->pb, s->frame_data, MAX_FRAMESIZE);
s->bits_per_sample = AV_RL16(edata_ptr);
/** dump the extradata */
for (i = 0; i < avctx->extradata_size; i++)
- av_dlog(avctx, "[%x] ", avctx->extradata[i]);
- av_dlog(avctx, "\n");
+ ff_dlog(avctx, "[%x] ", avctx->extradata[i]);
+ ff_dlog(avctx, "\n");
} else {
- av_log_ask_for_sample(avctx, "Unknown extradata size\n");
+ avpriv_request_sample(avctx, "Unknown extradata size");
return AVERROR_PATCHWELCOME;
}
/** get frame len */
bits = ff_wma_get_frame_len_bits(avctx->sample_rate, 3, s->decode_flags);
if (bits > WMAPRO_BLOCK_MAX_BITS) {
- av_log_missing_feature(avctx, "14-bits block sizes", 1);
+ avpriv_request_sample(avctx, "14-bit block sizes");
return AVERROR_PATCHWELCOME;
}
s->samples_per_frame = 1 << bits;
s->dynamic_range_compression = (s->decode_flags & 0x80);
if (s->max_num_subframes > MAX_SUBFRAMES) {
- av_log(avctx, AV_LOG_ERROR, "invalid number of subframes %i\n",
+ av_log(avctx, AV_LOG_ERROR, "invalid number of subframes %"PRId8"\n",
+ s->max_num_subframes);
+ return AVERROR_INVALIDDATA;
+ }
+
+ if (s->min_samples_per_subframe < WMAPRO_BLOCK_MIN_SIZE) {
+ av_log(avctx, AV_LOG_ERROR, "Invalid minimum block size %"PRId8"\n",
s->max_num_subframes);
return AVERROR_INVALIDDATA;
}
avctx->channels);
return AVERROR_INVALIDDATA;
} else if (avctx->channels > WMAPRO_MAX_CHANNELS) {
- av_log_ask_for_sample(avctx, "unsupported number of channels\n");
+ avpriv_request_sample(avctx,
+ "More than %d channels", WMAPRO_MAX_CHANNELS);
return AVERROR_PATCHWELCOME;
}
for (x = 0; x < num_possible_block_sizes; x++) {
int v = 0;
while (s->sfb_offsets[x][v + 1] << x < offset)
- ++v;
+ if (++v >= MAX_BANDS)
+ return AVERROR_INVALIDDATA;
s->sf_offsets[i][x][b] = v;
}
}
1.0 / (1 << (WMAPRO_BLOCK_MIN_BITS + i - 1))
/ (1 << (s->bits_per_sample - 1)));
- /** init MDCT windows: simple sinus window */
+ /** init MDCT windows: simple sine window */
for (i = 0; i < WMAPRO_BLOCK_SIZES; i++) {
const int win_idx = WMAPRO_BLOCK_MAX_BITS - i;
ff_init_ff_sine_windows(win_idx);
int i;
int offset = 0;
for (i = 0; i < s->channel[c].num_subframes; i++) {
- av_dlog(s->avctx, "frame[%i] channel[%i] subframe[%i]"
+ ff_dlog(s->avctx, "frame[%i] channel[%i] subframe[%i]"
" len %i\n", s->frame_num, c, i,
s->channel[c].subframe_len[i]);
s->channel[c].subframe_offset[i] = offset;
int remaining_channels = s->channels_for_cur_subframe;
if (get_bits1(&s->gb)) {
- av_log_ask_for_sample(s->avctx,
- "unsupported channel transform bit\n");
+ avpriv_request_sample(s->avctx,
+ "Channel transform bit");
return AVERROR_PATCHWELCOME;
}
if (chgroup->num_channels == 2) {
if (get_bits1(&s->gb)) {
if (get_bits1(&s->gb)) {
- av_log_ask_for_sample(s->avctx,
- "unsupported channel transform type\n");
+ avpriv_request_sample(s->avctx,
+ "Unknown channel transform type");
+ return AVERROR_PATCHWELCOME;
}
} else {
chgroup->transform = 1;
} else {
/** FIXME: more than 6 coupled channels not supported */
if (chgroup->num_channels > 6) {
- av_log_ask_for_sample(s->avctx,
- "coupled channels > 6\n");
+ avpriv_request_sample(s->avctx,
+ "Coupled channels > 6");
} else {
memcpy(chgroup->decorrelation_matrix,
default_decorrelation[chgroup->num_channels],
const uint16_t* run;
const float* level;
- av_dlog(s->avctx, "decode coefficients for channel %i\n", c);
+ ff_dlog(s->avctx, "decode coefficients for channel %i\n", c);
vlctable = get_bits1(&s->gb);
vlc = &coef_vlc[vlctable];
}
}
- av_dlog(s->avctx,
+ ff_dlog(s->avctx,
"processing subframe with offset %i len %i\n", offset, subframe_len);
/** get a list of all channels that contain the estimated block */
s->parsed_all_subframes = 1;
- av_dlog(s->avctx, "subframe is part of %i channels\n",
+ ff_dlog(s->avctx, "subframe is part of %i channels\n",
s->channels_for_cur_subframe);
/** calculate number of scale factor bands and their offsets */
cur_subwoofer_cutoff = s->subwoofer_cutoffs[s->table_idx];
/** configure the decoder for the current subframe */
+ offset += s->samples_per_frame >> 1;
+
for (i = 0; i < s->channels_for_cur_subframe; i++) {
int c = s->channel_indexes_for_cur_subframe[i];
- s->channel[c].coeffs = &s->channel[c].out[(s->samples_per_frame >> 1)
- + offset];
+ s->channel[c].coeffs = &s->channel[c].out[offset];
}
s->subframe_len = subframe_len;
int num_fill_bits;
if (!(num_fill_bits = get_bits(&s->gb, 2))) {
int len = get_bits(&s->gb, 4);
- num_fill_bits = get_bits(&s->gb, len) + 1;
+ num_fill_bits = get_bitsz(&s->gb, len) + 1;
}
if (num_fill_bits >= 0) {
/** no idea for what the following bit is used */
if (get_bits1(&s->gb)) {
- av_log_ask_for_sample(s->avctx, "reserved bit set\n");
+ avpriv_request_sample(s->avctx, "Reserved bit");
return AVERROR_PATCHWELCOME;
}
for (i = 0; i < s->channels_for_cur_subframe; i++) {
int c = s->channel_indexes_for_cur_subframe[i];
int num_vec_coeffs = get_bits(&s->gb, num_bits) << 2;
- if (num_vec_coeffs > WMAPRO_BLOCK_MAX_SIZE) {
+ if (num_vec_coeffs + offset > FF_ARRAY_ELEMS(s->channel[c].out)) {
av_log(s->avctx, AV_LOG_ERROR, "num_vec_coeffs %d is too large\n", num_vec_coeffs);
return AVERROR_INVALIDDATA;
}
return AVERROR_INVALIDDATA;
}
- av_dlog(s->avctx, "BITSTREAM: subframe header length was %i\n",
+ ff_dlog(s->avctx, "BITSTREAM: subframe header length was %i\n",
get_bits_count(&s->gb) - s->subframe_offset);
/** parse coefficients */
sizeof(*s->channel[c].coeffs) * subframe_len);
}
- av_dlog(s->avctx, "BITSTREAM: subframe length was %i\n",
+ ff_dlog(s->avctx, "BITSTREAM: subframe length was %i\n",
get_bits_count(&s->gb) - s->subframe_offset);
if (transmit_coeffs) {
if (s->len_prefix)
len = get_bits(gb, s->log2_frame_size);
- av_dlog(s->avctx, "decoding frame with length %x\n", len);
+ ff_dlog(s->avctx, "decoding frame with length %x\n", len);
/** decode tile information */
if (decode_tilehdr(s)) {
/** read drc info */
if (s->dynamic_range_compression) {
s->drc_gain = get_bits(gb, 8);
- av_dlog(s->avctx, "drc_gain %i\n", s->drc_gain);
+ ff_dlog(s->avctx, "drc_gain %i\n", s->drc_gain);
}
/** no idea what these are for, might be the number of samples
/** usually true for the first frame */
if (get_bits1(gb)) {
skip = get_bits(gb, av_log2(s->samples_per_frame * 2));
- av_dlog(s->avctx, "start skip: %i\n", skip);
+ ff_dlog(s->avctx, "start skip: %i\n", skip);
}
/** sometimes true for the last frame */
if (get_bits1(gb)) {
skip = get_bits(gb, av_log2(s->samples_per_frame * 2));
- av_dlog(s->avctx, "end skip: %i\n", skip);
+ ff_dlog(s->avctx, "end skip: %i\n", skip);
}
}
- av_dlog(s->avctx, "BITSTREAM: frame header length was %i\n",
+ ff_dlog(s->avctx, "BITSTREAM: frame header length was %i\n",
get_bits_count(gb) - s->frame_offset);
/** reset subframe states */
/* get output buffer */
frame->nb_samples = s->samples_per_frame;
- if ((ret = ff_get_buffer(avctx, frame)) < 0) {
+ if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) {
av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
s->packet_loss = 1;
return 0;
if (s->skip_frame) {
s->skip_frame = 0;
*got_frame_ptr = 0;
+ av_frame_unref(frame);
} else {
*got_frame_ptr = 1;
}
if (len != (get_bits_count(gb) - s->frame_offset) + 2) {
/** FIXME: not sure if this is always an error */
av_log(s->avctx, AV_LOG_ERROR,
- "frame[%i] would have to skip %i bits\n", s->frame_num,
+ "frame[%"PRIu32"] would have to skip %i bits\n",
+ s->frame_num,
len - (get_bits_count(gb) - s->frame_offset) - 1);
s->packet_loss = 1;
return 0;
int buflen;
/** when the frame data does not need to be concatenated, the input buffer
- is resetted and additional bits from the previous frame are copyed
+ is reset and additional bits from the previous frame are copied
and skipped later so that a fast byte copy is possible */
if (!append) {
buflen = (s->num_saved_bits + len + 8) >> 3;
if (len <= 0 || buflen > MAX_FRAMESIZE) {
- av_log_ask_for_sample(s->avctx, "input buffer too small\n");
+ avpriv_request_sample(s->avctx, "Too small input buffer");
+ s->packet_loss = 1;
+ return;
+ }
+
+ if (len > put_bits_left(&s->pb)) {
+ av_log(s->avctx, AV_LOG_ERROR,
+ "Cannot append %d bits, only %d bits available.\n",
+ len, put_bits_left(&s->pb));
s->packet_loss = 1;
return;
}
s->packet_done = 0;
/** sanity check for the buffer length */
- if (buf_size < avctx->block_align)
- return 0;
+ if (buf_size < avctx->block_align) {
+ av_log(avctx, AV_LOG_ERROR, "Input packet too small (%d < %d)\n",
+ buf_size, avctx->block_align);
+ return AVERROR_INVALIDDATA;
+ }
s->next_packet_start = buf_size - avctx->block_align;
buf_size = avctx->block_align;
/** get number of bits that need to be added to the previous frame */
num_bits_prev_frame = get_bits(gb, s->log2_frame_size);
- av_dlog(avctx, "packet[%d]: nbpf %x\n", avctx->frame_number,
+ ff_dlog(avctx, "packet[%d]: nbpf %x\n", avctx->frame_number,
num_bits_prev_frame);
/** check for packet loss */
if (!s->packet_loss &&
((s->packet_sequence_number + 1) & 0xF) != packet_sequence_number) {
s->packet_loss = 1;
- av_log(avctx, AV_LOG_ERROR, "Packet loss detected! seq %x vs %x\n",
+ av_log(avctx, AV_LOG_ERROR,
+ "Packet loss detected! seq %"PRIx8" vs %x\n",
s->packet_sequence_number, packet_sequence_number);
}
s->packet_sequence_number = packet_sequence_number;
/** append the previous frame data to the remaining data from the
previous packet to create a full frame */
save_bits(s, gb, num_bits_prev_frame, 1);
- av_dlog(avctx, "accumulated %x bits of frame data\n",
+ ff_dlog(avctx, "accumulated %x bits of frame data\n",
s->num_saved_bits - s->frame_offset);
/** decode the cross packet frame if it is valid */
if (!s->packet_loss)
decode_frame(s, data, got_frame_ptr);
} else if (s->num_saved_bits - s->frame_offset) {
- av_dlog(avctx, "ignoring %x previously saved bits\n",
+ ff_dlog(avctx, "ignoring %x previously saved bits\n",
s->num_saved_bits - s->frame_offset);
}
*/
AVCodec ff_wmapro_decoder = {
.name = "wmapro",
+ .long_name = NULL_IF_CONFIG_SMALL("Windows Media Audio 9 Professional"),
.type = AVMEDIA_TYPE_AUDIO,
.id = AV_CODEC_ID_WMAPRO,
.priv_data_size = sizeof(WMAProDecodeCtx),
.init = decode_init,
.close = decode_end,
.decode = decode_packet,
- .capabilities = CODEC_CAP_SUBFRAMES | CODEC_CAP_DR1,
+ .capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1,
.flush = flush,
- .long_name = NULL_IF_CONFIG_SMALL("Windows Media Audio 9 Professional"),
.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP,
AV_SAMPLE_FMT_NONE },
};