#include "bitstream.h"
#include "dcadata.h"
#include "dcahuff.h"
-#include "parser.h"
-
-/** DCA syncwords, also used for bitstream type detection */
-//@{
-#define DCA_MARKER_RAW_BE 0x7FFE8001
-#define DCA_MARKER_RAW_LE 0xFE7F0180
-#define DCA_MARKER_14B_BE 0x1FFFE800
-#define DCA_MARKER_14B_LE 0xFF1F00E8
-//@}
+#include "dca.h"
//#define TRACE
/** Pre-calculated cosine modulation coefs for the QMF */
static float cos_mod[544];
-static int av_always_inline get_bitalloc(GetBitContext *gb, BitAlloc *ba, int idx)
+static av_always_inline int get_bitalloc(GetBitContext *gb, BitAlloc *ba, int idx)
{
return get_vlc2(gb, ba->vlc[idx].table, ba->vlc[idx].bits, ba->wrap) + ba->offset;
}
/* Primary audio coding header */
int subframes; ///< number of subframes
+ int total_channels; ///< number of channels including extensions
int prim_channels; ///< number of primary audio channels
int subband_activity[DCA_PRIM_CHANNELS_MAX]; ///< subband activity count
int vq_start_subband[DCA_PRIM_CHANNELS_MAX]; ///< high frequency vq start subband
DSPContext dsp;
} DCAContext;
-static void dca_init_vlcs(void)
+static av_cold void dca_init_vlcs(void)
{
- static int vlcs_inited = 0;
+ static int vlcs_initialized = 0;
int i, j;
- if (vlcs_inited)
+ if (vlcs_initialized)
return;
dca_bitalloc_index.offset = 1;
- dca_bitalloc_index.wrap = 1;
+ dca_bitalloc_index.wrap = 2;
for (i = 0; i < 5; i++)
init_vlc(&dca_bitalloc_index.vlc[i], bitalloc_12_vlc_bits[i], 12,
bitalloc_12_bits[i], 1, 1,
bitalloc_bits[i][j], 1, 1,
bitalloc_codes[i][j], 2, 2, 1);
}
- vlcs_inited = 1;
+ vlcs_initialized = 1;
}
static inline void get_array(GetBitContext *gb, int *dst, int len, int bits)
s->dialog_norm = get_bits(&s->gb, 4);
/* FIXME: channels mixing levels */
- s->output = DCA_STEREO;
+ s->output = s->amode;
+ if(s->lfe) s->output |= DCA_LFE;
#ifdef TRACE
av_log(s->avctx, AV_LOG_DEBUG, "frame type: %i\n", s->frame_type);
/* Primary audio coding header */
s->subframes = get_bits(&s->gb, 4) + 1;
- s->prim_channels = get_bits(&s->gb, 3) + 1;
+ s->total_channels = get_bits(&s->gb, 3) + 1;
+ s->prim_channels = s->total_channels;
+ if (s->prim_channels > DCA_PRIM_CHANNELS_MAX)
+ s->prim_channels = DCA_PRIM_CHANNELS_MAX; /* We only support DTS core */
for (i = 0; i < s->prim_channels; i++) {
s->bitalloc[j][k] = get_bits(&s->gb, 5);
else if (s->bitalloc_huffman[j] == 5)
s->bitalloc[j][k] = get_bits(&s->gb, 4);
- else {
+ else if (s->bitalloc_huffman[j] == 7) {
+ av_log(s->avctx, AV_LOG_ERROR,
+ "Invalid bit allocation index\n");
+ return -1;
+ } else {
s->bitalloc[j][k] =
get_bitalloc(&s->gb, &dca_bitalloc_index, s->bitalloc_huffman[j]);
}
}
for (j = 0; j < s->prim_channels; j++) {
- uint32_t *scale_table;
+ const uint32_t *scale_table;
int scale_sum;
memset(s->scale_factor[j], 0, s->subband_activity[j] * sizeof(s->scale_factor[0][0][0]) * 2);
if (s->scalefactor_huffman[j] == 6)
- scale_table = (uint32_t *) scale_factor_quant7;
+ scale_table = scale_factor_quant7;
else
- scale_table = (uint32_t *) scale_factor_quant6;
+ scale_table = scale_factor_quant6;
/* When huffman coded, only the difference is encoded */
scale_sum = 0;
}
/* Stereo downmix coefficients */
- if (s->prim_channels > 2 && s->downmix) {
- for (j = 0; j < s->prim_channels; j++) {
- s->downmix_coef[j][0] = get_bits(&s->gb, 7);
- s->downmix_coef[j][1] = get_bits(&s->gb, 7);
+ if (s->prim_channels > 2) {
+ if(s->downmix) {
+ for (j = 0; j < s->prim_channels; j++) {
+ s->downmix_coef[j][0] = get_bits(&s->gb, 7);
+ s->downmix_coef[j][1] = get_bits(&s->gb, 7);
+ }
+ } else {
+ int am = s->amode & DCA_CHANNEL_MASK;
+ for (j = 0; j < s->prim_channels; j++) {
+ s->downmix_coef[j][0] = dca_default_coeffs[am][j][0];
+ s->downmix_coef[j][1] = dca_default_coeffs[am][j][1];
+ }
}
}
}
for (j = 0; j < s->prim_channels; j++) {
if (s->joint_intensity[j] > 0) {
+ int source_channel = s->joint_intensity[j] - 1;
av_log(s->avctx, AV_LOG_DEBUG, "Joint scale factor index:\n");
for (k = s->subband_activity[j]; k < s->subband_activity[source_channel]; k++)
av_log(s->avctx, AV_LOG_DEBUG, " %i", s->joint_scale_factor[j][k]);
for (k = s->vq_start_subband[j]; k < s->subband_activity[j]; k++)
av_log(s->avctx, AV_LOG_DEBUG, "VQ index: %i\n", s->high_freq_vq[j][k]);
if(s->lfe){
+ int lfe_samples = 2 * s->lfe * s->subsubframes;
av_log(s->avctx, AV_LOG_DEBUG, "LFE samples:\n");
for (j = lfe_samples; j < lfe_samples * 2; j++)
av_log(s->avctx, AV_LOG_DEBUG, " %f", s->lfe_data[j]);
float samples_in[32][8], float *samples_out,
float scale, float bias)
{
- float *prCoeff;
+ const float *prCoeff;
int i, j, k;
float praXin[33], *raXin = &praXin[1];
/* Select filter */
if (!s->multirate_inter) /* Non-perfect reconstruction */
- prCoeff = (float *) fir_32bands_nonperfect;
+ prCoeff = fir_32bands_nonperfect;
else /* Perfect reconstruction */
- prCoeff = (float *) fir_32bands_perfect;
+ prCoeff = fir_32bands_perfect;
/* Reconstructed channel sample index */
for (subindex = 0; subindex < 8; subindex++) {
}
/* downmixing routines */
-#define MIX_REAR1(samples, si1) \
- samples[i] += samples[si1]; \
- samples[i+256] += samples[si1];
+#define MIX_REAR1(samples, si1, rs, coef) \
+ samples[i] += samples[si1] * coef[rs][0]; \
+ samples[i+256] += samples[si1] * coef[rs][1];
-#define MIX_REAR2(samples, si1, si2) \
- samples[i] += samples[si1]; \
- samples[i+256] += samples[si2];
+#define MIX_REAR2(samples, si1, si2, rs, coef) \
+ samples[i] += samples[si1] * coef[rs][0] + samples[si2] * coef[rs+1][0]; \
+ samples[i+256] += samples[si1] * coef[rs][1] + samples[si2] * coef[rs+1][1];
-#define MIX_FRONT3(samples) \
+#define MIX_FRONT3(samples, coef) \
t = samples[i]; \
- samples[i] += samples[i+256]; \
- samples[i+256] = samples[i+512] + t;
+ samples[i] = t * coef[0][0] + samples[i+256] * coef[1][0] + samples[i+512] * coef[2][0]; \
+ samples[i+256] = t * coef[0][1] + samples[i+256] * coef[1][1] + samples[i+512] * coef[2][1];
#define DOWNMIX_TO_STEREO(op1, op2) \
for(i = 0; i < 256; i++){ \
op2 \
}
-static void dca_downmix(float *samples, int srcfmt)
+static void dca_downmix(float *samples, int srcfmt,
+ int downmix_coef[DCA_PRIM_CHANNELS_MAX][2])
{
int i;
float t;
+ float coef[DCA_PRIM_CHANNELS_MAX][2];
+
+ for(i=0; i<DCA_PRIM_CHANNELS_MAX; i++) {
+ coef[i][0] = dca_downmix_coeffs[downmix_coef[i][0]];
+ coef[i][1] = dca_downmix_coeffs[downmix_coef[i][1]];
+ }
switch (srcfmt) {
case DCA_MONO:
case DCA_STEREO:
break;
case DCA_3F:
- DOWNMIX_TO_STEREO(MIX_FRONT3(samples),);
+ DOWNMIX_TO_STEREO(MIX_FRONT3(samples, coef),);
break;
case DCA_2F1R:
- DOWNMIX_TO_STEREO(MIX_REAR1(samples, i + 512),);
+ DOWNMIX_TO_STEREO(MIX_REAR1(samples, i + 512, 2, coef),);
break;
case DCA_3F1R:
- DOWNMIX_TO_STEREO(MIX_FRONT3(samples),
- MIX_REAR1(samples, i + 768));
+ DOWNMIX_TO_STEREO(MIX_FRONT3(samples, coef),
+ MIX_REAR1(samples, i + 768, 3, coef));
break;
case DCA_2F2R:
- DOWNMIX_TO_STEREO(MIX_REAR2(samples, i + 512, i + 768),);
+ DOWNMIX_TO_STEREO(MIX_REAR2(samples, i + 512, i + 768, 2, coef),);
break;
case DCA_3F2R:
- DOWNMIX_TO_STEREO(MIX_FRONT3(samples),
- MIX_REAR2(samples, i + 768, i + 1024));
+ DOWNMIX_TO_STEREO(MIX_FRONT3(samples, coef),
+ MIX_REAR2(samples, i + 768, i + 1024, 3, coef));
break;
}
}
int k, l;
int subsubframe = s->current_subsubframe;
- float *quant_step_table;
+ const float *quant_step_table;
/* FIXME */
float subband_samples[DCA_PRIM_CHANNELS_MAX][DCA_SUBBANDS][8];
/* Select quantization step size table */
if (s->bit_rate == 0x1f)
- quant_step_table = (float *) lossless_quant_d;
+ quant_step_table = lossless_quant_d;
else
- quant_step_table = (float *) lossy_quant_d;
+ quant_step_table = lossy_quant_d;
for (k = 0; k < s->prim_channels; k++) {
for (l = 0; l < s->vq_start_subband[k]; l++) {
/* Down mixing */
if (s->prim_channels > dca_channels[s->output & DCA_CHANNEL_MASK]) {
- dca_downmix(s->samples, s->amode);
+ dca_downmix(s->samples, s->amode, s->downmix_coef);
}
/* Generate LFE samples for this subsubframe FIXME!!! */
s->lfe_data + lfe_samples +
2 * s->lfe * subsubframe,
&s->samples[256 * i_channels],
- 8388608.0, s->bias);
+ 256.0, 0 /* s->bias */);
/* Outputs 20bits pcm samples */
}
/**
* Convert bitstream to one representation based on sync marker
*/
-static int dca_convert_bitstream(uint8_t * src, int src_size, uint8_t * dst,
+static int dca_convert_bitstream(const uint8_t * src, int src_size, uint8_t * dst,
int max_size)
{
uint32_t mrk;
int i, tmp;
- uint16_t *ssrc = (uint16_t *) src, *sdst = (uint16_t *) dst;
+ const uint16_t *ssrc = (const uint16_t *) src;
+ uint16_t *sdst = (uint16_t *) dst;
PutBitContext pb;
- if((unsigned)src_size > (unsigned)max_size)
+ if((unsigned)src_size > (unsigned)max_size) {
+ av_log(NULL, AV_LOG_ERROR, "Input frame size larger then DCA_MAX_FRAME_SIZE!\n");
return -1;
+ }
mrk = AV_RB32(src);
switch (mrk) {
*/
static int dca_decode_frame(AVCodecContext * avctx,
void *data, int *data_size,
- uint8_t * buf, int buf_size)
+ const uint8_t * buf, int buf_size)
{
int i, j, k;
s->dca_buffer_size = dca_convert_bitstream(buf, buf_size, s->dca_buffer, DCA_MAX_FRAME_SIZE);
if (s->dca_buffer_size == -1) {
- av_log(avctx, AV_LOG_ERROR, "Not a DCA frame\n");
+ av_log(avctx, AV_LOG_ERROR, "Not a valid DCA frame\n");
return -1;
}
init_get_bits(&s->gb, s->dca_buffer, s->dca_buffer_size * 8);
if (dca_parse_frame_header(s) < 0) {
//seems like the frame is corrupt, try with the next one
+ *data_size=0;
return buf_size;
}
//set AVCodec values with parsed data
avctx->sample_rate = s->sample_rate;
- avctx->channels = 2; //FIXME
avctx->bit_rate = s->bit_rate;
- channels = dca_channels[s->output];
+ channels = s->prim_channels + !!s->lfe;
+ if(avctx->request_channels == 2 && s->prim_channels > 2) {
+ channels = 2;
+ s->output = DCA_STEREO;
+ }
+
+ /* There is nothing that prevents a dts frame to change channel configuration
+ but FFmpeg doesn't support that so only set the channels if it is previously
+ unset. Ideally during the first probe for channels the crc should be checked
+ and only set avctx->channels when the crc is ok. Right now the decoder could
+ set the channels based on a broken first frame.*/
+ if (!avctx->channels)
+ avctx->channels = channels;
+
if(*data_size < (s->sample_blocks / 8) * 256 * sizeof(int16_t) * channels)
return -1;
*data_size = 0;
* @param s pointer to the DCAContext
*/
-static void pre_calc_cosmod(DCAContext * s)
+static av_cold void pre_calc_cosmod(DCAContext * s)
{
int i, j, k;
- static int cosmod_inited = 0;
+ static int cosmod_initialized = 0;
- if(cosmod_inited) return;
+ if(cosmod_initialized) return;
for (j = 0, k = 0; k < 16; k++)
for (i = 0; i < 16; i++)
cos_mod[j++] = cos((2 * i + 1) * (2 * k + 1) * M_PI / 64);
for (k = 0; k < 16; k++)
cos_mod[j++] = -0.25 / (2.0 * sin((2 * k + 1) * M_PI / 128));
- cosmod_inited = 1;
+ cosmod_initialized = 1;
}
* @param avctx pointer to the AVCodecContext
*/
-static int dca_decode_init(AVCodecContext * avctx)
+static av_cold int dca_decode_init(AVCodecContext * avctx)
{
DCAContext *s = avctx->priv_data;
pre_calc_cosmod(s);
dsputil_init(&s->dsp, avctx);
+
+ /* allow downmixing to stereo */
+ if (avctx->channels > 0 && avctx->request_channels < avctx->channels &&
+ avctx->request_channels == 2) {
+ avctx->channels = avctx->request_channels;
+ }
+
return 0;
}
.priv_data_size = sizeof(DCAContext),
.init = dca_decode_init,
.decode = dca_decode_frame,
+ .long_name = NULL_IF_CONFIG_SMALL("DCA (DTS Coherent Acoustics)"),
};
-
-#ifdef CONFIG_DCA_PARSER
-
-typedef struct DCAParseContext {
- ParseContext pc;
- uint32_t lastmarker;
-} DCAParseContext;
-
-#define IS_MARKER(state, i, buf, buf_size) \
- ((state == DCA_MARKER_14B_LE && (i < buf_size-2) && (buf[i+1] & 0xF0) == 0xF0 && buf[i+2] == 0x07) \
- || (state == DCA_MARKER_14B_BE && (i < buf_size-2) && buf[i+1] == 0x07 && (buf[i+2] & 0xF0) == 0xF0) \
- || state == DCA_MARKER_RAW_LE || state == DCA_MARKER_RAW_BE)
-
-/**
- * finds the end of the current frame in the bitstream.
- * @return the position of the first byte of the next frame, or -1
- */
-static int dca_find_frame_end(DCAParseContext * pc1, const uint8_t * buf,
- int buf_size)
-{
- int start_found, i;
- uint32_t state;
- ParseContext *pc = &pc1->pc;
-
- start_found = pc->frame_start_found;
- state = pc->state;
-
- i = 0;
- if (!start_found) {
- for (i = 0; i < buf_size; i++) {
- state = (state << 8) | buf[i];
- if (IS_MARKER(state, i, buf, buf_size)) {
- if (pc1->lastmarker && state == pc1->lastmarker) {
- start_found = 1;
- break;
- } else if (!pc1->lastmarker) {
- start_found = 1;
- pc1->lastmarker = state;
- break;
- }
- }
- }
- }
- if (start_found) {
- for (; i < buf_size; i++) {
- state = (state << 8) | buf[i];
- if (state == pc1->lastmarker && IS_MARKER(state, i, buf, buf_size)) {
- pc->frame_start_found = 0;
- pc->state = -1;
- return i - 3;
- }
- }
- }
- pc->frame_start_found = start_found;
- pc->state = state;
- return END_NOT_FOUND;
-}
-
-static int dca_parse_init(AVCodecParserContext * s)
-{
- DCAParseContext *pc1 = s->priv_data;
-
- pc1->lastmarker = 0;
- return 0;
-}
-
-static int dca_parse(AVCodecParserContext * s,
- AVCodecContext * avctx,
- uint8_t ** poutbuf, int *poutbuf_size,
- const uint8_t * buf, int buf_size)
-{
- DCAParseContext *pc1 = s->priv_data;
- ParseContext *pc = &pc1->pc;
- int next;
-
- if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) {
- next = buf_size;
- } else {
- next = dca_find_frame_end(pc1, buf, buf_size);
-
- if (ff_combine_frame(pc, next, (uint8_t **) & buf, &buf_size) < 0) {
- *poutbuf = NULL;
- *poutbuf_size = 0;
- return buf_size;
- }
- }
- *poutbuf = (uint8_t *) buf;
- *poutbuf_size = buf_size;
- return next;
-}
-
-AVCodecParser dca_parser = {
- {CODEC_ID_DTS},
- sizeof(DCAParseContext),
- dca_parse_init,
- dca_parse,
- ff_parse_close,
-};
-#endif /* CONFIG_DCA_PARSER */