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->avctx->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->avctx->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]; } } av_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->channels_for_cur_subframe = 0; for (i = 0; i < s->avctx->channels; i++) { const int cur_subframe = s->channel[i].cur_subframe; /** subtract 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; av_dlog(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)) { avpriv_request_sample(s->avctx, "Reserved bit"); return AVERROR_PATCHWELCOME; } 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; /** decode number of vector coded coefficients */ if ((s->transmit_num_vec_coeffs = get_bits1(&s->gb))) { int num_bits = av_log2((s->subframe_len + 3)/4) + 1; 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) { av_log(s->avctx, AV_LOG_ERROR, "num_vec_coeffs %d is too large\n", num_vec_coeffs); return AVERROR_INVALIDDATA; } s->channel[c].num_vec_coeffs = num_vec_coeffs; } } else { for (i = 0; i < s->channels_for_cur_subframe; i++) { int c = s->channel_indexes_for_cur_subframe[i]; s->channel[c].num_vec_coeffs = s->subframe_len; } } /** 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; } av_dlog(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); } av_dlog(s->avctx, "BITSTREAM: subframe length was %i\n", get_bits_count(&s->gb) - s->subframe_offset); if (transmit_coeffs) { FFTContext *mdct = &s->mdct_ctx[av_log2(subframe_len) - WMAPRO_BLOCK_MIN_BITS]; /** 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->fdsp.vector_fmul_scalar(s->tmp + start, s->channel[c].coeffs + start, quant, end - start); } /** apply imdct (imdct_half == DCTIV with reverse) */ mdct->imdct_half(mdct, 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; }