#define DCA_NSYNCAUX 0x9A1105A0
+#define SAMPLES_PER_SUBBAND 8 // number of samples per subband per subsubframe
/** Bit allocation */
typedef struct BitAlloc {
if (!base_channel) {
s->subsubframes[s->current_subframe] = get_bits(&s->gb, 2) + 1;
- if (block_index + s->subsubframes[s->current_subframe] > s->sample_blocks/8) {
+ if (block_index + s->subsubframes[s->current_subframe] > (s->sample_blocks / SAMPLES_PER_SUBBAND)) {
s->subsubframes[s->current_subframe] = 1;
return AVERROR_INVALIDDATA;
}
}
static void qmf_32_subbands(DCAContext *s, int chans,
- float samples_in[32][8], float *samples_out,
+ float samples_in[32][SAMPLES_PER_SUBBAND], float *samples_out,
float scale)
{
const float *prCoeff;
/* FIXME: Totally unoptimized. Based on the reference code and
* http://multimedia.cx/mirror/dca-transform.pdf, with guessed tweaks
* for doubling the size. */
-static void qmf_64_subbands(DCAContext *s, int chans, float samples_in[64][8],
+static void qmf_64_subbands(DCAContext *s, int chans, float samples_in[64][SAMPLES_PER_SUBBAND],
float *samples_out, float scale)
{
float raXin[64];
for (i = s->subband_activity[chans]; i < 64; i++)
raXin[i] = 0.0;
- for (subindex = 0; subindex < 8; subindex++) {
+ for (subindex = 0; subindex < SAMPLES_PER_SUBBAND; subindex++) {
for (i = 0; i < s->subband_activity[chans]; i++)
raXin[i] = samples_in[i][subindex];
const float *quant_step_table;
/* FIXME */
- float (*subband_samples)[DCA_SUBBANDS][8] = s->subband_samples[block_index];
- LOCAL_ALIGNED_16(int32_t, block, [8 * DCA_SUBBANDS]);
+ float (*subband_samples)[DCA_SUBBANDS][SAMPLES_PER_SUBBAND] = s->subband_samples[block_index];
+ LOCAL_ALIGNED_16(int32_t, block, [SAMPLES_PER_SUBBAND * DCA_SUBBANDS]);
/*
* Audio data
*/
if (!abits) {
rscale[l] = 0;
- memset(block + 8 * l, 0, 8 * sizeof(block[0]));
+ memset(block + SAMPLES_PER_SUBBAND * l, 0, SAMPLES_PER_SUBBAND * sizeof(block[0]));
} else {
/* Deal with transients */
int sfi = s->transition_mode[k][l] && subsubframe >= s->transition_mode[k][l];
block_code1 = get_bits(&s->gb, size);
block_code2 = get_bits(&s->gb, size);
err = decode_blockcodes(block_code1, block_code2,
- levels, block + 8 * l);
+ levels, block + SAMPLES_PER_SUBBAND * l);
if (err) {
av_log(s->avctx, AV_LOG_ERROR,
"ERROR: block code look-up failed\n");
}
} else {
/* no coding */
- for (m = 0; m < 8; m++)
- block[8 * l + m] = get_sbits(&s->gb, abits - 3);
+ for (m = 0; m < SAMPLES_PER_SUBBAND; m++)
+ block[SAMPLES_PER_SUBBAND * l + m] = get_sbits(&s->gb, abits - 3);
}
} else {
/* Huffman coded */
- for (m = 0; m < 8; m++)
- block[8 * l + m] = get_bitalloc(&s->gb,
+ for (m = 0; m < SAMPLES_PER_SUBBAND; m++)
+ block[SAMPLES_PER_SUBBAND * l + m] = get_bitalloc(&s->gb,
&dca_smpl_bitalloc[abits], sel);
}
}
}
s->fmt_conv.int32_to_float_fmul_array8(&s->fmt_conv, subband_samples[k][0],
- block, rscale, 8 * s->vq_start_subband[k]);
+ block, rscale, SAMPLES_PER_SUBBAND * s->vq_start_subband[k]);
for (l = 0; l < s->vq_start_subband[k]; l++) {
int m;
ff_dca_adpcm_vb[s->prediction_vq[k][l]][3] *
s->subband_samples_hist[k][l][0]) *
(1.0f / 8192);
- for (m = 1; m < 8; m++) {
+ for (m = 1; m < SAMPLES_PER_SUBBAND; m++) {
float sum = ff_dca_adpcm_vb[s->prediction_vq[k][l]][0] *
subband_samples[k][l][m - 1];
for (n = 2; n <= 4; n++)
s->debug_flag |= 0x01;
}
s->dcadsp.decode_hf(subband_samples[k], s->high_freq_vq[k],
- ff_dca_high_freq_vq, subsubframe * 8,
+ ff_dca_high_freq_vq, subsubframe * SAMPLES_PER_SUBBAND,
s->scale_factor[k], s->vq_start_subband[k],
s->subband_activity[k]);
}
static int dca_filter_channels(DCAContext *s, int block_index, int upsample)
{
- float (*subband_samples)[DCA_SUBBANDS][8] = s->subband_samples[block_index];
+ float (*subband_samples)[DCA_SUBBANDS][SAMPLES_PER_SUBBAND] = s->subband_samples[block_index];
int k;
if (upsample) {
return ((ff_dca_dmixtable[code] ^ sign) - sign) * (1.0 / (1 << 15));
}
-/**
- * Main frame decoding function
- * FIXME add arguments
- */
-static int dca_decode_frame(AVCodecContext *avctx, void *data,
- int *got_frame_ptr, AVPacket *avpkt)
+static int scan_for_extensions(AVCodecContext *avctx)
{
- AVFrame *frame = data;
- const uint8_t *buf = avpkt->data;
- int buf_size = avpkt->size;
- int channel_mask;
- int channel_layout;
- int lfe_samples;
- int num_core_channels = 0;
- int i, ret;
- float **samples_flt;
- float *src_chan;
- float *dst_chan;
DCAContext *s = avctx->priv_data;
- int core_ss_end;
- int channels, full_channels;
- float scale;
- int achan;
- int chset;
- int mask;
- int lavc;
- int posn;
- int j, k;
- int endch;
- int upsample = 0;
-
- s->exss_ext_mask = 0;
- s->xch_present = 0;
-
- s->dca_buffer_size = AVERROR_INVALIDDATA;
- for (i = 0; i < buf_size - 3 && s->dca_buffer_size == AVERROR_INVALIDDATA; i++)
- s->dca_buffer_size = avpriv_dca_convert_bitstream(buf + i, buf_size - i, s->dca_buffer,
- DCA_MAX_FRAME_SIZE + DCA_MAX_EXSS_HEADER_SIZE);
-
- if (s->dca_buffer_size == AVERROR_INVALIDDATA) {
- av_log(avctx, AV_LOG_ERROR, "Not a valid DCA frame\n");
- return AVERROR_INVALIDDATA;
- }
-
- if ((ret = dca_parse_frame_header(s)) < 0) {
- // seems like the frame is corrupt, try with the next one
- return ret;
- }
- // set AVCodec values with parsed data
- avctx->sample_rate = s->sample_rate;
-
- s->profile = FF_PROFILE_DTS;
-
- for (i = 0; i < (s->sample_blocks / 8); i++) {
- if ((ret = dca_decode_block(s, 0, i))) {
- av_log(avctx, AV_LOG_ERROR, "error decoding block\n");
- return ret;
- }
- }
-
- /* record number of core channels incase less than max channels are requested */
- num_core_channels = s->prim_channels;
-
- if (s->prim_channels + !!s->lfe > 2 &&
- avctx->request_channel_layout == AV_CH_LAYOUT_STEREO) {
- /* Stereo downmix coefficients
- *
- * The decoder can only downmix to 2-channel, so we need to ensure
- * embedded downmix coefficients are actually targeting 2-channel.
- */
- if (s->core_downmix && (s->core_downmix_amode == DCA_STEREO ||
- s->core_downmix_amode == DCA_STEREO_TOTAL)) {
- for (i = 0; i < num_core_channels + !!s->lfe; i++) {
- /* Range checked earlier */
- s->downmix_coef[i][0] = dca_dmix_code(s->core_downmix_codes[i][0]);
- s->downmix_coef[i][1] = dca_dmix_code(s->core_downmix_codes[i][1]);
- }
- s->output = s->core_downmix_amode;
- } else {
- int am = s->amode & DCA_CHANNEL_MASK;
- if (am >= FF_ARRAY_ELEMS(ff_dca_default_coeffs)) {
- av_log(s->avctx, AV_LOG_ERROR,
- "Invalid channel mode %d\n", am);
- return AVERROR_INVALIDDATA;
- }
- if (num_core_channels + !!s->lfe >
- FF_ARRAY_ELEMS(ff_dca_default_coeffs[0])) {
- avpriv_request_sample(s->avctx, "Downmixing %d channels",
- s->prim_channels + !!s->lfe);
- return AVERROR_PATCHWELCOME;
- }
- for (i = 0; i < num_core_channels + !!s->lfe; i++) {
- s->downmix_coef[i][0] = ff_dca_default_coeffs[am][i][0];
- s->downmix_coef[i][1] = ff_dca_default_coeffs[am][i][1];
- }
- }
- ff_dlog(s->avctx, "Stereo downmix coeffs:\n");
- for (i = 0; i < num_core_channels + !!s->lfe; i++) {
- ff_dlog(s->avctx, "L, input channel %d = %f\n", i,
- s->downmix_coef[i][0]);
- ff_dlog(s->avctx, "R, input channel %d = %f\n", i,
- s->downmix_coef[i][1]);
- }
- ff_dlog(s->avctx, "\n");
- }
-
- if (s->ext_coding)
- s->core_ext_mask = ff_dca_ext_audio_descr_mask[s->ext_descr];
- else
- s->core_ext_mask = 0;
+ int core_ss_end, ret = 0;
core_ss_end = FFMIN(s->frame_size, s->dca_buffer_size) * 8;
while (core_ss_end - get_bits_count(&s->gb) >= 32) {
uint32_t bits = get_bits_long(&s->gb, 32);
+ int i;
switch (bits) {
case DCA_SYNCWORD_XCH: {
get_bits_long(&s->gb, 32) == DCA_SYNCWORD_SUBSTREAM)
ff_dca_exss_parse_header(s);
- avctx->profile = s->profile;
+ return ret;
+}
- full_channels = channels = s->prim_channels + !!s->lfe;
+static int set_channel_layout(AVCodecContext *avctx, int *channels, int num_core_channels)
+{
+ DCAContext *s = avctx->priv_data;
+ int i, j, chset, mask;
+ int channel_layout, channel_mask;
+ int posn, lavc;
/* If we have XXCH then the channel layout is managed differently */
/* note that XLL will also have another way to do things */
if (s->channel_order_tab[s->xch_base_channel] < 0)
return AVERROR_INVALIDDATA;
} else {
- channels = num_core_channels + !!s->lfe;
+ *channels = num_core_channels + !!s->lfe;
s->xch_present = 0; /* disable further xch processing */
if (s->lfe) {
avctx->channel_layout |= AV_CH_LOW_FREQUENCY;
s->channel_order_tab = ff_dca_channel_reorder_nolfe[s->amode];
}
- if (channels > !!s->lfe &&
- s->channel_order_tab[channels - 1 - !!s->lfe] < 0)
+ if (*channels > !!s->lfe &&
+ s->channel_order_tab[*channels - 1 - !!s->lfe] < 0)
return AVERROR_INVALIDDATA;
- if (av_get_channel_layout_nb_channels(avctx->channel_layout) != channels) {
- av_log(avctx, AV_LOG_ERROR, "Number of channels %d mismatches layout %d\n", channels, av_get_channel_layout_nb_channels(avctx->channel_layout));
+ if (av_get_channel_layout_nb_channels(avctx->channel_layout) != *channels) {
+ av_log(avctx, AV_LOG_ERROR, "Number of channels %d mismatches layout %d\n", *channels, av_get_channel_layout_nb_channels(avctx->channel_layout));
return AVERROR_INVALIDDATA;
}
if (num_core_channels + !!s->lfe > 2 &&
avctx->request_channel_layout == AV_CH_LAYOUT_STEREO) {
- channels = 2;
+ *channels = 2;
s->output = s->prim_channels == 2 ? s->amode : DCA_STEREO;
avctx->channel_layout = AV_CH_LAYOUT_STEREO;
}
channel_mask = s->xxch_core_spkmask;
{
- channels = s->prim_channels + !!s->lfe;
+ *channels = s->prim_channels + !!s->lfe;
for (i = 0; i < s->xxch_chset; i++) {
channel_mask |= s->xxch_spk_masks[i];
}
s->lfe_index = av_popcount(channel_layout & (AV_CH_LOW_FREQUENCY-1));
} else { /* native ordering */
- for (i = 0; i < channels; i++)
+ for (i = 0; i < *channels; i++)
s->xxch_order_tab[i] = i;
- s->lfe_index = channels - 1;
+ s->lfe_index = *channels - 1;
}
s->channel_order_tab = s->xxch_order_tab;
}
+ return 0;
+}
+
+/**
+ * Main frame decoding function
+ * FIXME add arguments
+ */
+static int dca_decode_frame(AVCodecContext *avctx, void *data,
+ int *got_frame_ptr, AVPacket *avpkt)
+{
+ AVFrame *frame = data;
+ const uint8_t *buf = avpkt->data;
+ int buf_size = avpkt->size;
+ int lfe_samples;
+ int num_core_channels = 0;
+ int i, ret;
+ float **samples_flt;
+ float *src_chan;
+ float *dst_chan;
+ DCAContext *s = avctx->priv_data;
+ int channels, full_channels;
+ float scale;
+ int achan;
+ int chset;
+ int mask;
+ int j, k;
+ int endch;
+ int upsample = 0;
+
+ s->exss_ext_mask = 0;
+ s->xch_present = 0;
+
+ s->dca_buffer_size = AVERROR_INVALIDDATA;
+ for (i = 0; i < buf_size - 3 && s->dca_buffer_size == AVERROR_INVALIDDATA; i++)
+ s->dca_buffer_size = avpriv_dca_convert_bitstream(buf + i, buf_size - i, s->dca_buffer,
+ DCA_MAX_FRAME_SIZE + DCA_MAX_EXSS_HEADER_SIZE);
+
+ if (s->dca_buffer_size == AVERROR_INVALIDDATA) {
+ av_log(avctx, AV_LOG_ERROR, "Not a valid DCA frame\n");
+ return AVERROR_INVALIDDATA;
+ }
+
+ if ((ret = dca_parse_frame_header(s)) < 0) {
+ // seems like the frame is corrupt, try with the next one
+ return ret;
+ }
+ // set AVCodec values with parsed data
+ avctx->sample_rate = s->sample_rate;
+
+ s->profile = FF_PROFILE_DTS;
+
+ for (i = 0; i < (s->sample_blocks / SAMPLES_PER_SUBBAND); i++) {
+ if ((ret = dca_decode_block(s, 0, i))) {
+ av_log(avctx, AV_LOG_ERROR, "error decoding block\n");
+ return ret;
+ }
+ }
+
+ /* record number of core channels incase less than max channels are requested */
+ num_core_channels = s->prim_channels;
+
+ if (s->prim_channels + !!s->lfe > 2 &&
+ avctx->request_channel_layout == AV_CH_LAYOUT_STEREO) {
+ /* Stereo downmix coefficients
+ *
+ * The decoder can only downmix to 2-channel, so we need to ensure
+ * embedded downmix coefficients are actually targeting 2-channel.
+ */
+ if (s->core_downmix && (s->core_downmix_amode == DCA_STEREO ||
+ s->core_downmix_amode == DCA_STEREO_TOTAL)) {
+ for (i = 0; i < num_core_channels + !!s->lfe; i++) {
+ /* Range checked earlier */
+ s->downmix_coef[i][0] = dca_dmix_code(s->core_downmix_codes[i][0]);
+ s->downmix_coef[i][1] = dca_dmix_code(s->core_downmix_codes[i][1]);
+ }
+ s->output = s->core_downmix_amode;
+ } else {
+ int am = s->amode & DCA_CHANNEL_MASK;
+ if (am >= FF_ARRAY_ELEMS(ff_dca_default_coeffs)) {
+ av_log(s->avctx, AV_LOG_ERROR,
+ "Invalid channel mode %d\n", am);
+ return AVERROR_INVALIDDATA;
+ }
+ if (num_core_channels + !!s->lfe >
+ FF_ARRAY_ELEMS(ff_dca_default_coeffs[0])) {
+ avpriv_request_sample(s->avctx, "Downmixing %d channels",
+ s->prim_channels + !!s->lfe);
+ return AVERROR_PATCHWELCOME;
+ }
+ for (i = 0; i < num_core_channels + !!s->lfe; i++) {
+ s->downmix_coef[i][0] = ff_dca_default_coeffs[am][i][0];
+ s->downmix_coef[i][1] = ff_dca_default_coeffs[am][i][1];
+ }
+ }
+ ff_dlog(s->avctx, "Stereo downmix coeffs:\n");
+ for (i = 0; i < num_core_channels + !!s->lfe; i++) {
+ ff_dlog(s->avctx, "L, input channel %d = %f\n", i,
+ s->downmix_coef[i][0]);
+ ff_dlog(s->avctx, "R, input channel %d = %f\n", i,
+ s->downmix_coef[i][1]);
+ }
+ ff_dlog(s->avctx, "\n");
+ }
+
+ if (s->ext_coding)
+ s->core_ext_mask = ff_dca_ext_audio_descr_mask[s->ext_descr];
+ else
+ s->core_ext_mask = 0;
+
+ ret = scan_for_extensions(avctx);
+
+ avctx->profile = s->profile;
+
+ full_channels = channels = s->prim_channels + !!s->lfe;
+
+ ret = set_channel_layout(avctx, &channels, num_core_channels);
+ if (ret < 0)
+ return ret;
+
/* get output buffer */
- frame->nb_samples = 256 * (s->sample_blocks / 8);
+ frame->nb_samples = 256 * (s->sample_blocks / SAMPLES_PER_SUBBAND);
if (s->exss_ext_mask & DCA_EXT_EXSS_XLL) {
int xll_nb_samples = s->xll_segments * s->xll_smpl_in_seg;
/* Check for invalid/unsupported conditions first */
}
/* filter to get final output */
- for (i = 0; i < (s->sample_blocks / 8); i++) {
+ for (i = 0; i < (s->sample_blocks / SAMPLES_PER_SUBBAND); i++) {
int ch;
unsigned block = upsample ? 512 : 256;
for (ch = 0; ch < channels; ch++)
}
/* update lfe history */
- lfe_samples = 2 * s->lfe * (s->sample_blocks / 8);
+ lfe_samples = 2 * s->lfe * (s->sample_blocks / SAMPLES_PER_SUBBAND);
for (i = 0; i < 2 * s->lfe * 4; i++)
s->lfe_data[i] = s->lfe_data[i + lfe_samples];