static int decode_subframe(WmallDecodeCtx *s) { int offset = s->samples_per_frame; int subframe_len = s->samples_per_frame; int total_samples = s->samples_per_frame * s->num_channels; int i, j, rawpcm_tile, padding_zeroes, res; 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++) { 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]; } } /* 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; /* 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; s->seekable_tile = get_bits1(&s->gb); if (s->seekable_tile) { clear_codec_buffers(s); s->do_arith_coding = get_bits1(&s->gb); if (s->do_arith_coding) { avpriv_request_sample(s->avctx, "Arithmetic coding"); return AVERROR_PATCHWELCOME; } s->do_ac_filter = get_bits1(&s->gb); s->do_inter_ch_decorr = get_bits1(&s->gb); s->do_mclms = get_bits1(&s->gb); if (s->do_ac_filter) decode_ac_filter(s); if (s->do_mclms) decode_mclms(s); if ((res = decode_cdlms(s)) < 0) return res; s->movave_scaling = get_bits(&s->gb, 3); s->quant_stepsize = get_bits(&s->gb, 8) + 1; reset_codec(s); } else if (!s->cdlms[0][0].order) { av_log(s->avctx, AV_LOG_DEBUG, "Waiting for seekable tile\n"); s->frame.nb_samples = 0; return -1; } rawpcm_tile = get_bits1(&s->gb); for (i = 0; i < s->num_channels; i++) s->is_channel_coded[i] = 1; if (!rawpcm_tile) { for (i = 0; i < s->num_channels; i++) s->is_channel_coded[i] = get_bits1(&s->gb); if (s->bV3RTM) { // LPC s->do_lpc = get_bits1(&s->gb); if (s->do_lpc) { decode_lpc(s); avpriv_request_sample(s->avctx, "Expect wrong output since " "inverse LPC filter"); } } else s->do_lpc = 0; } if (get_bits1(&s->gb)) padding_zeroes = get_bits(&s->gb, 5); else padding_zeroes = 0; if (rawpcm_tile) { int bits = s->bits_per_sample - padding_zeroes; if (bits <= 0) { av_log(s->avctx, AV_LOG_ERROR, "Invalid number of padding bits in raw PCM tile\n"); return AVERROR_INVALIDDATA; } av_dlog(s->avctx, "RAWPCM %d bits per sample. " "total %d bits, remain=%d\n", bits, bits * s->num_channels * subframe_len, get_bits_count(&s->gb)); for (i = 0; i < s->num_channels; i++) for (j = 0; j < subframe_len; j++) s->channel_coeffs[i][j] = get_sbits(&s->gb, bits); } else { for (i = 0; i < s->num_channels; i++) if (s->is_channel_coded[i]) { decode_channel_residues(s, i, subframe_len); if (s->seekable_tile) use_high_update_speed(s, i); else use_normal_update_speed(s, i); revert_cdlms(s, i, 0, subframe_len); } else { memset(s->channel_residues[i], 0, sizeof(**s->channel_residues) * subframe_len); } } if (s->do_mclms) revert_mclms(s, subframe_len); if (s->do_inter_ch_decorr) revert_inter_ch_decorr(s, subframe_len); if (s->do_ac_filter) revert_acfilter(s, subframe_len); /* Dequantize */ if (s->quant_stepsize != 1) for (i = 0; i < s->num_channels; i++) for (j = 0; j < subframe_len; j++) s->channel_residues[i][j] *= s->quant_stepsize; /* Write to proper output buffer depending on bit-depth */ for (i = 0; i < s->channels_for_cur_subframe; i++) { int c = s->channel_indexes_for_cur_subframe[i]; int subframe_len = s->channel[c].subframe_len[s->channel[c].cur_subframe]; for (j = 0; j < subframe_len; j++) { if (s->bits_per_sample == 16) { *s->samples_16[c]++ = (int16_t) s->channel_residues[c][j] << padding_zeroes; } else { *s->samples_32[c]++ = s->channel_residues[c][j] << padding_zeroes; } } } /* 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; }