+/** Read parameters for primitive matrices. */
+
+static int read_matrix_params(MLPDecodeContext *m, unsigned int substr, GetBitContext *gbp)
+{
+ SubStream *s = &m->substream[substr];
+ unsigned int mat, ch;
+ const int max_primitive_matrices = m->avctx->codec_id == AV_CODEC_ID_MLP
+ ? MAX_MATRICES_MLP
+ : MAX_MATRICES_TRUEHD;
+
+ if (m->matrix_changed++ > 1) {
+ av_log(m->avctx, AV_LOG_ERROR, "Matrices may change only once per access unit.\n");
+ return AVERROR_INVALIDDATA;
+ }
+
+ s->num_primitive_matrices = get_bits(gbp, 4);
+
+ if (s->num_primitive_matrices > max_primitive_matrices) {
+ av_log(m->avctx, AV_LOG_ERROR,
+ "Number of primitive matrices cannot be greater than %d.\n",
+ max_primitive_matrices);
+ return AVERROR_INVALIDDATA;
+ }
+
+ for (mat = 0; mat < s->num_primitive_matrices; mat++) {
+ int frac_bits, max_chan;
+ s->matrix_out_ch[mat] = get_bits(gbp, 4);
+ frac_bits = get_bits(gbp, 4);
+ s->lsb_bypass [mat] = get_bits1(gbp);
+
+ if (s->matrix_out_ch[mat] > s->max_matrix_channel) {
+ av_log(m->avctx, AV_LOG_ERROR,
+ "Invalid channel %d specified as output from matrix.\n",
+ s->matrix_out_ch[mat]);
+ return AVERROR_INVALIDDATA;
+ }
+ if (frac_bits > 14) {
+ av_log(m->avctx, AV_LOG_ERROR,
+ "Too many fractional bits specified.\n");
+ return AVERROR_INVALIDDATA;
+ }
+
+ max_chan = s->max_matrix_channel;
+ if (!s->noise_type)
+ max_chan+=2;
+
+ for (ch = 0; ch <= max_chan; ch++) {
+ int coeff_val = 0;
+ if (get_bits1(gbp))
+ coeff_val = get_sbits(gbp, frac_bits + 2);
+
+ s->matrix_coeff[mat][ch] = coeff_val << (14 - frac_bits);
+ }
+
+ if (s->noise_type)
+ s->matrix_noise_shift[mat] = get_bits(gbp, 4);
+ else
+ s->matrix_noise_shift[mat] = 0;
+ }
+
+ return 0;
+}
+
+/** Read channel parameters. */
+
+static int read_channel_params(MLPDecodeContext *m, unsigned int substr,
+ GetBitContext *gbp, unsigned int ch)
+{
+ SubStream *s = &m->substream[substr];
+ ChannelParams *cp = &s->channel_params[ch];
+ FilterParams *fir = &cp->filter_params[FIR];
+ FilterParams *iir = &cp->filter_params[IIR];
+ int ret;
+
+ if (s->param_presence_flags & PARAM_FIR)
+ if (get_bits1(gbp))
+ if ((ret = read_filter_params(m, gbp, substr, ch, FIR)) < 0)
+ return ret;
+
+ if (s->param_presence_flags & PARAM_IIR)
+ if (get_bits1(gbp))
+ if ((ret = read_filter_params(m, gbp, substr, ch, IIR)) < 0)
+ return ret;
+
+ if (fir->order + iir->order > 8) {
+ av_log(m->avctx, AV_LOG_ERROR, "Total filter orders too high.\n");
+ return AVERROR_INVALIDDATA;
+ }
+
+ if (fir->order && iir->order &&
+ fir->shift != iir->shift) {
+ av_log(m->avctx, AV_LOG_ERROR,
+ "FIR and IIR filters must use the same precision.\n");
+ return AVERROR_INVALIDDATA;
+ }
+ /* The FIR and IIR filters must have the same precision.
+ * To simplify the filtering code, only the precision of the
+ * FIR filter is considered. If only the IIR filter is employed,
+ * the FIR filter precision is set to that of the IIR filter, so
+ * that the filtering code can use it. */
+ if (!fir->order && iir->order)
+ fir->shift = iir->shift;
+
+ if (s->param_presence_flags & PARAM_HUFFOFFSET)
+ if (get_bits1(gbp))
+ cp->huff_offset = get_sbits(gbp, 15);
+
+ cp->codebook = get_bits(gbp, 2);
+ cp->huff_lsbs = get_bits(gbp, 5);
+
+ if (cp->huff_lsbs > 24) {
+ av_log(m->avctx, AV_LOG_ERROR, "Invalid huff_lsbs.\n");
+ return AVERROR_INVALIDDATA;
+ }
+
+ cp->sign_huff_offset = calculate_sign_huff(m, substr, ch);
+
+ return 0;
+}
+