static status read_frame(decoders_ALACDecoder *self, BitstreamReader* mdat, array_ia* frameset_channels, unsigned channel_count) { unsigned has_sample_count; unsigned uncompressed_LSBs; unsigned not_compressed; unsigned sample_count; /*read frame header*/ if (mdat->read(mdat, 16) != 0) { return alacdec_ValueError(self, "invalid unused bits"); } has_sample_count = mdat->read(mdat, 1); uncompressed_LSBs = mdat->read(mdat, 2); not_compressed = mdat->read(mdat, 1); if (has_sample_count == 0) sample_count = self->max_samples_per_frame; else sample_count = mdat->read(mdat, 32); if (not_compressed == 1) { unsigned channel; unsigned i; array_ia* frame_channels = self->frame_channels; /*if uncompressed, read and return a bunch of verbatim samples*/ frame_channels->reset(frame_channels); for (channel = 0; channel < channel_count; channel++) frame_channels->append(frame_channels); for (i = 0; i < sample_count; i++) { for (channel = 0; channel < channel_count; channel++) { frame_channels->_[channel]->append( frame_channels->_[channel], mdat->read_signed(mdat, self->bits_per_sample)); } } for (channel = 0; channel < channel_count; channel++) frame_channels->_[channel]->swap( frame_channels->_[channel], frameset_channels->append(frameset_channels)); return OK; } else { unsigned interlacing_shift; unsigned interlacing_leftweight; unsigned channel; unsigned i; unsigned sample_size; array_i* LSBs = NULL; array_i* residuals = self->residuals; array_ia* frame_channels = self->frame_channels; array_i* channel_data; frame_channels->reset(frame_channels); /*if compressed, read interlacing shift and leftweight*/ interlacing_shift = mdat->read(mdat, 8); interlacing_leftweight = mdat->read(mdat, 8); /*read a subframe header per channel*/ for (channel = 0; channel < channel_count; channel++) { read_subframe_header(mdat, &(self->subframe_headers[channel])); } /*if uncompressed LSBs, read a block of partial samples to prepend*/ if (uncompressed_LSBs > 0) { LSBs = self->uncompressed_LSBs; LSBs->reset(LSBs); for (i = 0; i < (channel_count * sample_count); i++) LSBs->append(LSBs, mdat->read(mdat, uncompressed_LSBs * 8)); } sample_size = (self->bits_per_sample - (uncompressed_LSBs * 8) + (channel_count - 1)); /*read a residual block per channel and calculate the subframe's samples*/ for (channel = 0; channel < channel_count; channel++) { residuals->reset(residuals); read_residuals(mdat, residuals, sample_count, sample_size, self->initial_history, self->history_multiplier, self->maximum_k); decode_subframe( frame_channels->append(frame_channels), sample_size, residuals, self->subframe_headers[channel].qlp_coeff, self->subframe_headers[channel].qlp_shift_needed); } /*if stereo, decorrelate channels according to interlacing shift and interlacing leftweight*/ if ((channel_count == 2) && (interlacing_leftweight > 0)) { decorrelate_channels(frame_channels->_[0], frame_channels->_[1], interlacing_shift, interlacing_leftweight); } /*if uncompressed LSBs, prepend partial samples to output*/ if (uncompressed_LSBs > 0) { for (channel = 0; channel < channel_count; channel++) { channel_data = frame_channels->_[channel]; for (i = 0; i < sample_count; i++) { channel_data->_[i] = ((channel_data->_[i] << uncompressed_LSBs * 8) | LSBs->_[(i * channel_count) + channel]); } } } /*finally, return frame's channel data*/ for (channel = 0; channel < channel_count; channel++) frame_channels->_[channel]->swap( frame_channels->_[channel], frameset_channels->append(frameset_channels)); return OK; } }
static int decode_frame(FLACContext *s) { int i, ret; GetBitContext *gb = &s->gb; FLACFrameInfo fi; if ((ret = ff_flac_decode_frame_header(s->avctx, gb, &fi, 0)) < 0) { av_log(s->avctx, AV_LOG_ERROR, "invalid frame header\n"); return ret; } if (s->channels && fi.channels != s->channels && s->got_streaminfo) { s->channels = s->avctx->channels = fi.channels; ff_flac_set_channel_layout(s->avctx); ret = allocate_buffers(s); if (ret < 0) return ret; } s->channels = s->avctx->channels = fi.channels; if (!s->avctx->channel_layout) ff_flac_set_channel_layout(s->avctx); s->ch_mode = fi.ch_mode; if (!s->bps && !fi.bps) { av_log(s->avctx, AV_LOG_ERROR, "bps not found in STREAMINFO or frame header\n"); return AVERROR_INVALIDDATA; } if (!fi.bps) { fi.bps = s->bps; } else if (s->bps && fi.bps != s->bps) { av_log(s->avctx, AV_LOG_ERROR, "switching bps mid-stream is not " "supported\n"); return AVERROR_INVALIDDATA; } if (!s->bps) { s->bps = s->avctx->bits_per_raw_sample = fi.bps; flac_set_bps(s); } if (!s->max_blocksize) s->max_blocksize = FLAC_MAX_BLOCKSIZE; if (fi.blocksize > s->max_blocksize) { av_log(s->avctx, AV_LOG_ERROR, "blocksize %d > %d\n", fi.blocksize, s->max_blocksize); return AVERROR_INVALIDDATA; } s->blocksize = fi.blocksize; if (!s->samplerate && !fi.samplerate) { av_log(s->avctx, AV_LOG_ERROR, "sample rate not found in STREAMINFO" " or frame header\n"); return AVERROR_INVALIDDATA; } if (fi.samplerate == 0) fi.samplerate = s->samplerate; s->samplerate = s->avctx->sample_rate = fi.samplerate; if (!s->got_streaminfo) { ret = allocate_buffers(s); if (ret < 0) return ret; ff_flacdsp_init(&s->dsp, s->avctx->sample_fmt, s->bps); s->got_streaminfo = 1; dump_headers(s->avctx, (FLACStreaminfo *)s); } // dump_headers(s->avctx, (FLACStreaminfo *)s); /* subframes */ for (i = 0; i < s->channels; i++) { if ((ret = decode_subframe(s, i)) < 0) return ret; } align_get_bits(gb); /* frame footer */ skip_bits(gb, 16); /* data crc */ return 0; }
static status_t decode_compressed_frame(BitstreamReader *br, const struct alac_parameters *params, unsigned uncompressed_LSBs, unsigned bits_per_sample, unsigned block_size, unsigned channels, int channel_0[], int channel_1[]) { const unsigned uncompressed_bits = uncompressed_LSBs * 8; const unsigned sample_size = bits_per_sample - uncompressed_bits + (channels - 1); const unsigned interlacing_shift = br->read(br, 8); const unsigned interlacing_leftweight = br->read(br, 8); struct subframe_header subframe_header[channels]; int subframe[channels][block_size]; unsigned i; unsigned c; status_t status; for (c = 0; c < channels; c++) { if ((status = read_subframe_header(br, &subframe_header[c])) != OK) { return status; } } if (!uncompressed_bits) { /*the common case where there's no uncompressed least-significant bits to handle, such as 16bps audio*/ for (c = 0; c < channels; c++) { int residual[block_size]; read_residual_block(br, params, sample_size, block_size, residual); decode_subframe(block_size, sample_size, &subframe_header[c], residual, subframe[c]); } /*perform channel decorrelation, if necessary*/ if (channels == 2) { if (interlacing_leftweight > 0) { decorrelate_channels(block_size, interlacing_shift, interlacing_leftweight, subframe[0], subframe[1], channel_0, channel_1); } else { memcpy(channel_0, subframe[0], block_size * sizeof(int)); memcpy(channel_1, subframe[1], block_size * sizeof(int)); } } else { memcpy(channel_0, subframe[0], block_size * sizeof(int)); } } else { /*the case where there are least significant bits to handle such as for 24bps audio*/ int LSBs[channels][block_size]; for (i = 0; i < block_size; i++) { for (c = 0; c < channels; c++) { LSBs[c][i] = br->read(br, uncompressed_bits); } } for (c = 0; c < channels; c++) { int residual[block_size]; read_residual_block(br, params, sample_size, block_size, residual); decode_subframe(block_size, sample_size, &subframe_header[c], residual, subframe[c]); } /*perform channel decorrelation, if necessary*/ if (channels == 2) { if (interlacing_leftweight > 0) { decorrelate_channels(block_size, interlacing_shift, interlacing_leftweight, subframe[0], subframe[1], channel_0, channel_1); } else { memcpy(channel_0, subframe[0], block_size * sizeof(int)); memcpy(channel_1, subframe[1], block_size * sizeof(int)); } /*apply uncompressed LSBs to channel data*/ for (i = 0; i < block_size; i++) { channel_0[i] <<= uncompressed_bits; channel_0[i] |= LSBs[0][i]; channel_1[i] <<= uncompressed_bits; channel_1[i] |= LSBs[1][i]; } } else { memcpy(channel_0, subframe[0], block_size * sizeof(int)); /*apply uncompressed LSBs to channel data*/ for (i = 0; i < block_size; i++) { channel_0[i] <<= uncompressed_bits; channel_0[i] |= LSBs[0][i]; } } } return OK; }