+/**
+ *@brief Apply sine window and reconstruct the output buffer.
+ *@param s codec context
+ */
+static void wmapro_window(WMAProDecodeCtx *s)
+{
+ int i;
+ for (i = 0; i < s->channels_for_cur_subframe; i++) {
+ int c = s->channel_indexes_for_cur_subframe[i];
+ float* window;
+ int winlen = s->channel[c].prev_block_len;
+ float* start = s->channel[c].coeffs - (winlen >> 1);
+
+ if (s->subframe_len < winlen) {
+ start += (winlen - s->subframe_len) >> 1;
+ winlen = s->subframe_len;
+ }
+
+ window = s->windows[av_log2(winlen) - BLOCK_MIN_BITS];
+
+ winlen >>= 1;
+
+ s->dsp.vector_fmul_window(start, start, start + winlen,
+ window, 0, winlen);
+
+ s->channel[c].prev_block_len = s->subframe_len;
+ }
+}
+
+/**
+ *@brief Decode a single subframe (block).
+ *@param s codec context
+ *@return 0 on success, < 0 when decoding failed
+ */
+static int decode_subframe(WMAProDecodeCtx *s)
+{
+ int offset = s->samples_per_frame;
+ int subframe_len = s->samples_per_frame;
+ int i;
+ int total_samples = s->samples_per_frame * s->num_channels;
+ int transmit_coeffs = 0;
+ int cur_subwoofer_cutoff;
+
+ s->subframe_offset = get_bits_count(&s->gb);
+
+ /** reset channel context and find the next block offset and size
+ == the next block of the channel with the smallest number of
+ decoded samples
+ */
+ for (i = 0; i < s->num_channels; i++) {
+ s->channel[i].grouped = 0;
+ if (offset > s->channel[i].decoded_samples) {
+ offset = s->channel[i].decoded_samples;
+ subframe_len =
+ s->channel[i].subframe_len[s->channel[i].cur_subframe];
+ }
+ }
+
+ dprintf(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->channels_for_cur_subframe = 0;
+ for (i = 0; i < s->num_channels; i++) {
+ const int cur_subframe = s->channel[i].cur_subframe;
+ /** substract already processed samples */
+ total_samples -= s->channel[i].decoded_samples;
+
+ /** and count if there are multiple subframes that match our profile */
+ if (offset == s->channel[i].decoded_samples &&
+ subframe_len == s->channel[i].subframe_len[cur_subframe]) {
+ total_samples -= s->channel[i].subframe_len[cur_subframe];
+ s->channel[i].decoded_samples +=
+ s->channel[i].subframe_len[cur_subframe];
+ s->channel_indexes_for_cur_subframe[s->channels_for_cur_subframe] = i;
+ ++s->channels_for_cur_subframe;
+ }
+ }
+
+ /** check if the frame will be complete after processing the
+ estimated block */
+ if (!total_samples)
+ s->parsed_all_subframes = 1;
+
+
+ dprintf(s->avctx, "subframe is part of %i channels\n",
+ s->channels_for_cur_subframe);
+
+ /** calculate number of scale factor bands and their offsets */
+ s->table_idx = av_log2(s->samples_per_frame/subframe_len);
+ s->num_bands = s->num_sfb[s->table_idx];
+ s->cur_sfb_offsets = s->sfb_offsets[s->table_idx];
+ cur_subwoofer_cutoff = s->subwoofer_cutoffs[s->table_idx];
+
+ /** configure the decoder for the current subframe */
+ 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->subframe_len = subframe_len;
+ s->esc_len = av_log2(s->subframe_len - 1) + 1;
+
+ /** skip extended header if any */
+ if (get_bits1(&s->gb)) {
+ 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;
+ }
+
+ if (num_fill_bits >= 0) {
+ if (get_bits_count(&s->gb) + num_fill_bits > s->num_saved_bits) {
+ av_log(s->avctx, AV_LOG_ERROR, "invalid number of fill bits\n");
+ return AVERROR_INVALIDDATA;
+ }
+
+ skip_bits_long(&s->gb, num_fill_bits);
+ }
+ }
+
+ /** 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");
+ return AVERROR_INVALIDDATA;
+ }
+
+
+ if (decode_channel_transform(s) < 0)
+ return AVERROR_INVALIDDATA;
+
+
+ for (i = 0; i < s->channels_for_cur_subframe; i++) {
+ int c = s->channel_indexes_for_cur_subframe[i];
+ if ((s->channel[c].transmit_coefs = get_bits1(&s->gb)))
+ transmit_coeffs = 1;
+ }
+
+ if (transmit_coeffs) {
+ int step;
+ int quant_step = 90 * s->bits_per_sample >> 4;
+ if ((get_bits1(&s->gb))) {
+ /** FIXME: might change run level mode decision */
+ av_log_ask_for_sample(s->avctx, "unsupported quant step coding\n");
+ return AVERROR_INVALIDDATA;
+ }
+ /** decode quantization step */
+ step = get_sbits(&s->gb, 6);
+ quant_step += step;
+ if (step == -32 || step == 31) {
+ const int sign = (step == 31) - 1;
+ int quant = 0;
+ while (get_bits_count(&s->gb) + 5 < s->num_saved_bits &&
+ (step = get_bits(&s->gb, 5)) == 31) {
+ quant += 31;
+ }
+ quant_step += ((quant + step) ^ sign) - sign;
+ }
+ if (quant_step < 0) {
+ av_log(s->avctx, AV_LOG_DEBUG, "negative quant step\n");
+ }
+
+ /** decode quantization step modifiers for every channel */
+
+ if (s->channels_for_cur_subframe == 1) {
+ s->channel[s->channel_indexes_for_cur_subframe[0]].quant_step = quant_step;
+ } else {
+ int modifier_len = get_bits(&s->gb, 3);
+ for (i = 0; i < s->channels_for_cur_subframe; i++) {
+ int c = s->channel_indexes_for_cur_subframe[i];
+ s->channel[c].quant_step = quant_step;
+ if (get_bits1(&s->gb)) {
+ if (modifier_len) {
+ s->channel[c].quant_step += get_bits(&s->gb, modifier_len) + 1;
+ } else
+ ++s->channel[c].quant_step;
+ }
+ }
+ }
+
+ /** decode scale factors */
+ if (decode_scale_factors(s) < 0)
+ return AVERROR_INVALIDDATA;
+ }
+
+ dprintf(s->avctx, "BITSTREAM: subframe header length was %i\n",
+ get_bits_count(&s->gb) - s->subframe_offset);
+
+ /** parse coefficients */
+ for (i = 0; i < s->channels_for_cur_subframe; i++) {
+ int c = s->channel_indexes_for_cur_subframe[i];
+ if (s->channel[c].transmit_coefs &&
+ get_bits_count(&s->gb) < s->num_saved_bits) {
+ decode_coeffs(s, c);
+ } else
+ memset(s->channel[c].coeffs, 0,
+ sizeof(*s->channel[c].coeffs) * subframe_len);
+ }
+
+ dprintf(s->avctx, "BITSTREAM: subframe length was %i\n",
+ get_bits_count(&s->gb) - s->subframe_offset);
+
+ if (transmit_coeffs) {
+ /** reconstruct the per channel data */
+ inverse_channel_transform(s);
+ for (i = 0; i < s->channels_for_cur_subframe; i++) {
+ int c = s->channel_indexes_for_cur_subframe[i];
+ const int* sf = s->channel[c].scale_factors;
+ int b;
+
+ if (c == s->lfe_channel)
+ memset(&s->tmp[cur_subwoofer_cutoff], 0, sizeof(*s->tmp) *
+ (subframe_len - cur_subwoofer_cutoff));
+
+ /** inverse quantization and rescaling */
+ for (b = 0; b < s->num_bands; b++) {
+ const int end = FFMIN(s->cur_sfb_offsets[b+1], s->subframe_len);
+ const int exp = s->channel[c].quant_step -
+ (s->channel[c].max_scale_factor - *sf++) *
+ s->channel[c].scale_factor_step;
+ const float quant = pow(10.0, exp / 20.0);
+ int start = s->cur_sfb_offsets[b];
+ s->dsp.vector_fmul_scalar(s->tmp + start,
+ s->channel[c].coeffs + start,
+ quant, end - start);
+ }
+
+ /** apply imdct (ff_imdct_half == DCTIV with reverse) */
+ ff_imdct_half(&s->mdct_ctx[av_log2(subframe_len) - BLOCK_MIN_BITS],
+ s->channel[c].coeffs, s->tmp);
+ }
+ }
+
+ /** window and overlapp-add */
+ wmapro_window(s);
+
+ /** handled one subframe */
+ for (i = 0; i < s->channels_for_cur_subframe; i++) {
+ int c = s->channel_indexes_for_cur_subframe[i];
+ if (s->channel[c].cur_subframe >= s->channel[c].num_subframes) {
+ av_log(s->avctx, AV_LOG_ERROR, "broken subframe\n");
+ return AVERROR_INVALIDDATA;
+ }
+ ++s->channel[c].cur_subframe;
+ }
+
+ return 0;
+}
+
+/**
+ *@brief Decode one WMA frame.
+ *@param s codec context
+ *@return 0 if the trailer bit indicates that this is the last frame,
+ * 1 if there are additional frames
+ */
+static int decode_frame(WMAProDecodeCtx *s)
+{
+ GetBitContext* gb = &s->gb;
+ int more_frames = 0;
+ int len = 0;
+ int i;
+
+ /** check for potential output buffer overflow */
+ if (s->num_channels * s->samples_per_frame > s->samples_end - s->samples) {
+ /** return an error if no frame could be decoded at all */
+ av_log(s->avctx, AV_LOG_ERROR,
+ "not enough space for the output samples\n");
+ s->packet_loss = 1;
+ return 0;
+ }
+
+ /** get frame length */
+ if (s->len_prefix)
+ len = get_bits(gb, s->log2_frame_size);
+
+ dprintf(s->avctx, "decoding frame with length %x\n", len);
+
+ /** decode tile information */
+ if (decode_tilehdr(s)) {
+ s->packet_loss = 1;
+ return 0;
+ }
+
+ /** read postproc transform */
+ if (s->num_channels > 1 && get_bits1(gb)) {
+ av_log_ask_for_sample(s->avctx, "Unsupported postproc transform found\n");
+ s->packet_loss = 1;
+ return 0;
+ }
+
+ /** read drc info */
+ if (s->dynamic_range_compression) {
+ s->drc_gain = get_bits(gb, 8);
+ dprintf(s->avctx, "drc_gain %i\n", s->drc_gain);
+ }
+
+ /** no idea what these are for, might be the number of samples
+ that need to be skipped at the beginning or end of a stream */
+ if (get_bits1(gb)) {
+ int skip;
+
+ /** usually true for the first frame */
+ if (get_bits1(gb)) {
+ skip = get_bits(gb, av_log2(s->samples_per_frame * 2));
+ dprintf(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));
+ dprintf(s->avctx, "end skip: %i\n", skip);
+ }
+
+ }
+
+ dprintf(s->avctx, "BITSTREAM: frame header length was %i\n",
+ get_bits_count(gb) - s->frame_offset);
+
+ /** reset subframe states */
+ s->parsed_all_subframes = 0;
+ for (i = 0; i < s->num_channels; i++) {
+ s->channel[i].decoded_samples = 0;
+ s->channel[i].cur_subframe = 0;
+ s->channel[i].reuse_sf = 0;
+ }
+
+ /** decode all subframes */
+ while (!s->parsed_all_subframes) {
+ if (decode_subframe(s) < 0) {
+ s->packet_loss = 1;
+ return 0;
+ }
+ }
+
+ /** interleave samples and write them to the output buffer */
+ for (i = 0; i < s->num_channels; i++) {
+ float* ptr;
+ int incr = s->num_channels;
+ float* iptr = s->channel[i].out;
+ int x;
+
+ ptr = s->samples + i;
+
+ for (x = 0; x < s->samples_per_frame; x++) {
+ *ptr = av_clipf(*iptr++, -1.0, 32767.0 / 32768.0);
+ ptr += incr;
+ }
+
+ /** reuse second half of the IMDCT output for the next frame */
+ memcpy(&s->channel[i].out[0],
+ &s->channel[i].out[s->samples_per_frame],
+ s->samples_per_frame * sizeof(*s->channel[i].out) >> 1);
+ }
+
+ if (s->skip_frame) {
+ s->skip_frame = 0;
+ } else
+ s->samples += s->num_channels * s->samples_per_frame;
+
+ 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, len - (get_bits_count(gb) - s->frame_offset) - 1);
+ s->packet_loss = 1;
+ return 0;
+ }
+
+ /** skip the rest of the frame data */
+ skip_bits_long(gb, len - (get_bits_count(gb) - s->frame_offset) - 1);
+
+ /** decode trailer bit */
+ more_frames = get_bits1(gb);
+
+ ++s->frame_num;
+ return more_frames;
+}
+
+/**
+ *@brief Calculate remaining input buffer length.
+ *@param s codec context
+ *@param gb bitstream reader context
+ *@return remaining size in bits
+ */
+static int remaining_bits(WMAProDecodeCtx *s, GetBitContext *gb)
+{
+ return s->buf_bit_size - get_bits_count(gb);
+}
+
+/**
+ *@brief Fill the bit reservoir with a (partial) frame.
+ *@param s codec context
+ *@param gb bitstream reader context
+ *@param len length of the partial frame
+ *@param append decides wether to reset the buffer or not
+ */
+static void save_bits(WMAProDecodeCtx *s, GetBitContext* gb, int len,
+ int append)
+{
+ 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
+ and skipped later so that a fast byte copy is possible */
+
+ if (!append) {
+ s->frame_offset = get_bits_count(gb) & 7;
+ s->num_saved_bits = s->frame_offset;
+ init_put_bits(&s->pb, s->frame_data, MAX_FRAMESIZE);
+ }
+
+ 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");
+ s->packet_loss = 1;
+ return;
+ }
+
+ s->num_saved_bits += len;
+ if (!append) {
+ ff_copy_bits(&s->pb, gb->buffer + (get_bits_count(gb) >> 3),
+ s->num_saved_bits);
+ } else {
+ int align = 8 - (get_bits_count(gb) & 7);
+ align = FFMIN(align, len);
+ put_bits(&s->pb, align, get_bits(gb, align));
+ len -= align;
+ ff_copy_bits(&s->pb, gb->buffer + (get_bits_count(gb) >> 3), len);
+ }
+ skip_bits_long(gb, len);
+
+ {
+ PutBitContext tmp = s->pb;
+ flush_put_bits(&tmp);
+ }
+
+ init_get_bits(&s->gb, s->frame_data, s->num_saved_bits);
+ skip_bits(&s->gb, s->frame_offset);
+}
+
+/**
+ *@brief Decode a single WMA packet.
+ *@param avctx codec context
+ *@param data the output buffer
+ *@param data_size number of bytes that were written to the output buffer
+ *@param avpkt input packet
+ *@return number of bytes that were read from the input buffer
+ */
+static int decode_packet(AVCodecContext *avctx,
+ void *data, int *data_size, AVPacket* avpkt)
+{
+ WMAProDecodeCtx *s = avctx->priv_data;
+ GetBitContext* gb = &s->pgb;
+ const uint8_t* buf = avpkt->data;
+ int buf_size = avpkt->size;
+ int num_bits_prev_frame;
+ int packet_sequence_number;
+
+ s->samples = data;
+ s->samples_end = (float*)((int8_t*)data + *data_size);
+ *data_size = 0;
+
+ if (s->packet_done || s->packet_loss) {
+ s->packet_done = 0;
+ s->buf_bit_size = buf_size << 3;
+
+ /** sanity check for the buffer length */
+ if (buf_size < avctx->block_align)
+ return 0;
+
+ buf_size = avctx->block_align;
+
+ /** parse packet header */
+ init_get_bits(gb, buf, s->buf_bit_size);
+ packet_sequence_number = get_bits(gb, 4);
+ skip_bits(gb, 2);
+
+ /** get number of bits that need to be added to the previous frame */
+ num_bits_prev_frame = get_bits(gb, s->log2_frame_size);
+ dprintf(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",
+ s->packet_sequence_number, packet_sequence_number);
+ }
+ s->packet_sequence_number = packet_sequence_number;
+
+ if (num_bits_prev_frame > 0) {
+ /** 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);
+ dprintf(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);
+ } else if (s->num_saved_bits - s->frame_offset) {
+ dprintf(avctx, "ignoring %x previously saved bits\n",
+ s->num_saved_bits - s->frame_offset);
+ }
+
+ s->packet_loss = 0;
+
+ } else {
+ int frame_size;
+ s->buf_bit_size = avpkt->size << 3;
+ init_get_bits(gb, avpkt->data, s->buf_bit_size);
+ skip_bits(gb, s->packet_offset);
+ if (remaining_bits(s, gb) > s->log2_frame_size &&
+ (frame_size = show_bits(gb, s->log2_frame_size)) &&
+ frame_size <= remaining_bits(s, gb)) {
+ save_bits(s, gb, frame_size, 0);
+ s->packet_done = !decode_frame(s);
+ } else
+ s->packet_done = 1;
+ }
+
+ if (s->packet_done && !s->packet_loss &&
+ remaining_bits(s, gb) > 0) {
+ /** save the rest of the data so that it can be decoded
+ with the next packet */
+ save_bits(s, gb, remaining_bits(s, gb), 0);
+ }
+
+ *data_size = (int8_t *)s->samples - (int8_t *)data;
+ s->packet_offset = get_bits_count(gb) & 7;
+
+ return (s->packet_loss) ? AVERROR_INVALIDDATA : get_bits_count(gb) >> 3;
+}
+
+/**
+ *@brief Clear decoder buffers (for seeking).
+ *@param avctx codec context
+ */
+static void flush(AVCodecContext *avctx)
+{
+ WMAProDecodeCtx *s = avctx->priv_data;
+ int i;
+ /** reset output buffer as a part of it is used during the windowing of a
+ new frame */
+ for (i = 0; i < s->num_channels; i++)
+ memset(s->channel[i].out, 0, s->samples_per_frame *
+ sizeof(*s->channel[i].out));
+ s->packet_loss = 1;
+}
+
+
+/**
+ *@brief wmapro decoder
+ */
+AVCodec wmapro_decoder = {
+ "wmapro",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_WMAPRO,
+ sizeof(WMAProDecodeCtx),
+ decode_init,
+ NULL,
+ decode_end,
+ decode_packet,
+ .capabilities = CODEC_CAP_SUBFRAMES,
+ .flush= flush,
+ .long_name = NULL_IF_CONFIG_SMALL("Windows Media Audio 9 Professional"),
+};