#include "libavutil/internal.h"
#include "libavutil/intreadwrite.h"
#include "libavutil/mathematics.h"
+#include "libavutil/opt.h"
#include "libavutil/samplefmt.h"
#include "avcodec.h"
#include "fft.h"
//#define TRACE
#define DCA_PRIM_CHANNELS_MAX (7)
-#define DCA_SUBBANDS (32)
#define DCA_ABITS_MAX (32) /* Should be 28 */
#define DCA_SUBSUBFRAMES_MAX (4)
#define DCA_SUBFRAMES_MAX (16)
#define DCA_BUFFER_PADDING_SIZE 1024
+#define DCA_NSYNCAUX 0x9A1105A0
+
/** Bit allocation */
typedef struct {
int offset; ///< code values offset
}
typedef struct {
+ AVClass *class; ///< class for AVOptions
AVCodecContext *avctx;
/* Frame header */
int frame_type; ///< type of the current frame
int prediction_vq[DCA_PRIM_CHANNELS_MAX][DCA_SUBBANDS]; ///< prediction VQ coefs
int bitalloc[DCA_PRIM_CHANNELS_MAX][DCA_SUBBANDS]; ///< bit allocation index
int transition_mode[DCA_PRIM_CHANNELS_MAX][DCA_SUBBANDS]; ///< transition mode (transients)
- int scale_factor[DCA_PRIM_CHANNELS_MAX][DCA_SUBBANDS][2]; ///< scale factors (2 if transient)
+ int32_t scale_factor[DCA_PRIM_CHANNELS_MAX][DCA_SUBBANDS][2];///< scale factors (2 if transient)
int joint_huff[DCA_PRIM_CHANNELS_MAX]; ///< joint subband scale factors codebook
int joint_scale_factor[DCA_PRIM_CHANNELS_MAX][DCA_SUBBANDS]; ///< joint subband scale factors
float downmix_coef[DCA_PRIM_CHANNELS_MAX + 1][2]; ///< stereo downmix coefficients
uint8_t core_downmix_amode; ///< audio channel arrangement of embedded downmix
uint16_t core_downmix_codes[DCA_PRIM_CHANNELS_MAX + 1][4]; ///< embedded downmix coefficients (9-bit codes)
- int high_freq_vq[DCA_PRIM_CHANNELS_MAX][DCA_SUBBANDS]; ///< VQ encoded high frequency subbands
+ int32_t high_freq_vq[DCA_PRIM_CHANNELS_MAX][DCA_SUBBANDS]; ///< VQ encoded high frequency subbands
float lfe_data[2 * DCA_LFE_MAX * (DCA_BLOCKS_MAX + 4)]; ///< Low frequency effect data
int lfe_scale_factor;
/* XCh extension information */
int xch_present; ///< XCh extension present and valid
int xch_base_channel; ///< index of first (only) channel containing XCH data
+ int xch_disable; ///< whether the XCh extension should be decoded or not
/* ExSS header parser */
int static_fields; ///< static fields present
static void lfe_interpolation_fir(DCAContext *s, int decimation_select,
int num_deci_sample, float *samples_in,
- float *samples_out, float scale)
+ float *samples_out)
{
/* samples_in: An array holding decimated samples.
* Samples in current subframe starts from samples_in[0],
* samples_out: An array holding interpolated samples
*/
- int decifactor;
+ int idx;
const float *prCoeff;
int deciindex;
/* Select decimation filter */
if (decimation_select == 1) {
- decifactor = 64;
+ idx = 1;
prCoeff = lfe_fir_128;
} else {
- decifactor = 32;
+ idx = 0;
prCoeff = lfe_fir_64;
}
/* Interpolation */
for (deciindex = 0; deciindex < num_deci_sample; deciindex++) {
- s->dcadsp.lfe_fir(samples_out, samples_in, prCoeff, decifactor, scale);
+ s->dcadsp.lfe_fir[idx](samples_out, samples_in, prCoeff);
samples_in++;
- samples_out += 2 * decifactor;
+ samples_out += 2 * 32 * (1 + idx);
}
}
switch (srcfmt) {
case DCA_MONO:
- case DCA_CHANNEL:
- case DCA_STEREO_TOTAL:
- case DCA_STEREO_SUMDIFF:
case DCA_4F2R:
av_log(NULL, 0, "Not implemented!\n");
break;
+ case DCA_CHANNEL:
case DCA_STEREO:
+ case DCA_STEREO_TOTAL:
+ case DCA_STEREO_SUMDIFF:
break;
case DCA_3F:
c = channel_mapping[0];
static const uint8_t abits_sizes[7] = { 7, 10, 12, 13, 15, 17, 19 };
static const uint8_t abits_levels[7] = { 3, 5, 7, 9, 13, 17, 25 };
-#ifndef int8x8_fmul_int32
-static inline void int8x8_fmul_int32(float *dst, const int8_t *src, int scale)
-{
- float fscale = scale / 16.0;
- int i;
- for (i = 0; i < 8; i++)
- dst[i] = src[i] * fscale;
-}
-#endif
-
static int dca_subsubframe(DCAContext *s, int base_channel, int block_index)
{
int k, l;
*/
if (s->prediction_mode[k][l]) {
int n;
- for (m = 0; m < 8; m++) {
- for (n = 1; n <= 4; n++)
+ if (s->predictor_history)
+ subband_samples[k][l][0] += (adpcm_vb[s->prediction_vq[k][l]][0] *
+ s->subband_samples_hist[k][l][3] +
+ adpcm_vb[s->prediction_vq[k][l]][1] *
+ s->subband_samples_hist[k][l][2] +
+ adpcm_vb[s->prediction_vq[k][l]][2] *
+ s->subband_samples_hist[k][l][1] +
+ adpcm_vb[s->prediction_vq[k][l]][3] *
+ s->subband_samples_hist[k][l][0]) *
+ (1.0f / 8192);
+ for (m = 1; m < 8; m++) {
+ float sum = adpcm_vb[s->prediction_vq[k][l]][0] *
+ subband_samples[k][l][m - 1];
+ for (n = 2; n <= 4; n++)
if (m >= n)
- subband_samples[k][l][m] +=
- (adpcm_vb[s->prediction_vq[k][l]][n - 1] *
- subband_samples[k][l][m - n] / 8192);
+ sum += adpcm_vb[s->prediction_vq[k][l]][n - 1] *
+ subband_samples[k][l][m - n];
else if (s->predictor_history)
- subband_samples[k][l][m] +=
- (adpcm_vb[s->prediction_vq[k][l]][n - 1] *
- s->subband_samples_hist[k][l][m - n + 4] / 8192);
+ sum += adpcm_vb[s->prediction_vq[k][l]][n - 1] *
+ s->subband_samples_hist[k][l][m - n + 4];
+ subband_samples[k][l][m] += sum * 1.0f / 8192;
}
}
}
/*
* Decode VQ encoded high frequencies
*/
- for (l = s->vq_start_subband[k]; l < s->subband_activity[k]; l++) {
- /* 1 vector -> 32 samples but we only need the 8 samples
- * for this subsubframe. */
- int hfvq = s->high_freq_vq[k][l];
-
+ if (s->subband_activity[k] > s->vq_start_subband[k]) {
if (!s->debug_flag & 0x01) {
av_log(s->avctx, AV_LOG_DEBUG,
"Stream with high frequencies VQ coding\n");
s->debug_flag |= 0x01;
}
-
- int8x8_fmul_int32(subband_samples[k][l],
- &high_freq_vq[hfvq][subsubframe * 8],
- s->scale_factor[k][l][0]);
+ s->dcadsp.decode_hf(subband_samples[k], s->high_freq_vq[k],
+ high_freq_vq, subsubframe * 8,
+ s->scale_factor[k], s->vq_start_subband[k],
+ s->subband_activity[k]);
}
}
/* Backup predictor history for adpcm */
for (k = base_channel; k < s->prim_channels; k++)
for (l = 0; l < s->vq_start_subband[k]; l++)
- memcpy(s->subband_samples_hist[k][l],
- &subband_samples[k][l][4],
- 4 * sizeof(subband_samples[0][0][0]));
+ AV_COPY128(s->subband_samples_hist[k][l], &subband_samples[k][l][4]);
return 0;
}
}
/* Generate LFE samples for this subsubframe FIXME!!! */
- if (s->output & DCA_LFE) {
+ if (s->lfe) {
lfe_interpolation_fir(s, s->lfe, 2 * s->lfe,
s->lfe_data + 2 * s->lfe * (block_index + 4),
- s->samples_chanptr[dca_lfe_index[s->amode]],
- 1.0 / (256.0 * 32768.0));
+ s->samples_chanptr[dca_lfe_index[s->amode]]);
/* Outputs 20bits pcm samples */
}
static int dca_subframe_footer(DCAContext *s, int base_channel)
{
int in, out, aux_data_count, aux_data_end, reserved;
+ uint32_t nsyncaux;
/*
* Unpack optional information
aux_data_end = 8 * aux_data_count + get_bits_count(&s->gb);
- if (get_bits_long(&s->gb, 32) != 0x9A1105A0) // nSYNCAUX
+ if ((nsyncaux = get_bits_long(&s->gb, 32)) != DCA_NSYNCAUX) {
+ av_log(s->avctx, AV_LOG_ERROR, "nSYNCAUX mismatch %#"PRIx32"\n",
+ nsyncaux);
return AVERROR_INVALIDDATA;
+ }
if (get_bits1(&s->gb)) { // bAUXTimeStampFlag
avpriv_request_sample(s->avctx,
}
if ((s->core_downmix = get_bits1(&s->gb))) {
- switch (get_bits(&s->gb, 3)) {
+ int am = get_bits(&s->gb, 3);
+ switch (am) {
case 0:
s->core_downmix_amode = DCA_MONO;
break;
s->core_downmix_amode = DCA_3F1R;
break;
default:
+ av_log(s->avctx, AV_LOG_ERROR,
+ "Invalid mode %d for embedded downmix coefficients\n",
+ am);
return AVERROR_INVALIDDATA;
}
for (out = 0; out < dca_channels[s->core_downmix_amode]; out++) {
for (in = 0; in < s->prim_channels + !!s->lfe; in++) {
uint16_t tmp = get_bits(&s->gb, 9);
- if ((tmp & 0xFF) > 241)
+ if ((tmp & 0xFF) > 241) {
+ av_log(s->avctx, AV_LOG_ERROR,
+ "Invalid downmix coefficient code %"PRIu16"\n",
+ tmp);
return AVERROR_INVALIDDATA;
+ }
s->core_downmix_codes[in][out] = tmp;
}
}
skip_bits(&s->gb, 16); // nAUXCRC16
// additional data (reserved, cf. ETSI TS 102 114 V1.4.1)
- if ((reserved = (aux_data_end - get_bits_count(&s->gb))) < 0)
+ if ((reserved = (aux_data_end - get_bits_count(&s->gb))) < 0) {
+ av_log(s->avctx, AV_LOG_ERROR,
+ "Overread auxiliary data by %d bits\n", -reserved);
return AVERROR_INVALIDDATA;
- else if (reserved) {
+ } else if (reserved) {
avpriv_request_sample(s->avctx,
"Core auxiliary data reserved content");
skip_bits_long(&s->gb, reserved);
* from the asset header */
}
+static float dca_dmix_code(unsigned code)
+{
+ int sign = (code >> 8) - 1;
+ code &= 0xff;
+ return ((dca_dmixtable[code] ^ sign) - sign) * (1.0 / (1U << 15));
+}
+
/**
* Main frame decoding function
* FIXME add arguments
return AVERROR_INVALIDDATA;
}
- init_get_bits(&s->gb, s->dca_buffer, s->dca_buffer_size * 8);
if ((ret = dca_parse_frame_header(s)) < 0) {
//seems like the frame is corrupt, try with the next one
return ret;
if (s->amode < 16) {
avctx->channel_layout = dca_core_channel_layout[s->amode];
+ if (s->prim_channels + !!s->lfe > 2 &&
+ avctx->request_channel_layout == AV_CH_LAYOUT_STEREO) {
+ /*
+ * Neither the core's auxiliary data nor our default tables contain
+ * downmix coefficients for the additional channel coded in the XCh
+ * extension, so when we're doing a Stereo downmix, don't decode it.
+ */
+ s->xch_disable = 1;
+ }
+
#if FF_API_REQUEST_CHANNELS
FF_DISABLE_DEPRECATION_WARNINGS
- if (s->xch_present && (!avctx->request_channels ||
- avctx->request_channels > num_core_channels + !!s->lfe)) {
+ if (s->xch_present && !s->xch_disable &&
+ (!avctx->request_channels ||
+ avctx->request_channels > num_core_channels + !!s->lfe)) {
FF_ENABLE_DEPRECATION_WARNINGS
#else
- if (s->xch_present) {
+ if (s->xch_present && !s->xch_disable) {
#endif
avctx->channel_layout |= AV_CH_BACK_CENTER;
if (s->lfe) {
s->channel_order_tab[channels - 1 - !!s->lfe] < 0)
return AVERROR_INVALIDDATA;
- if (s->prim_channels + !!s->lfe > 2 &&
+ if (num_core_channels + !!s->lfe > 2 &&
avctx->request_channel_layout == AV_CH_LAYOUT_STEREO) {
channels = 2;
- s->output = DCA_STEREO;
+ s->output = s->prim_channels == 2 ? s->amode : DCA_STEREO;
avctx->channel_layout = AV_CH_LAYOUT_STEREO;
/* Stereo downmix coefficients
*/
if (s->core_downmix && (s->core_downmix_amode == DCA_STEREO ||
s->core_downmix_amode == DCA_STEREO_TOTAL)) {
- int sign, code;
- for (i = 0; i < s->prim_channels + !!s->lfe; i++) {
- sign = s->core_downmix_codes[i][0] & 0x100 ? 1 : -1;
- code = s->core_downmix_codes[i][0] & 0x0FF;
- s->downmix_coef[i][0] = (!code ? 0.0f :
- sign * dca_dmixtable[code - 1]);
- sign = s->core_downmix_codes[i][1] & 0x100 ? 1 : -1;
- code = s->core_downmix_codes[i][1] & 0x0FF;
- s->downmix_coef[i][1] = (!code ? 0.0f :
- sign * dca_dmixtable[code - 1]);
+ 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(dca_default_coeffs)) {
"Invalid channel mode %d\n", am);
return AVERROR_INVALIDDATA;
}
- if (s->prim_channels + !!s->lfe >
+ if (num_core_channels + !!s->lfe >
FF_ARRAY_ELEMS(dca_default_coeffs[0])) {
avpriv_request_sample(s->avctx, "Downmixing %d channels",
s->prim_channels + !!s->lfe);
return AVERROR_PATCHWELCOME;
}
- for (i = 0; i < s->prim_channels + !!s->lfe; i++) {
+ for (i = 0; i < num_core_channels + !!s->lfe; i++) {
s->downmix_coef[i][0] = dca_default_coeffs[am][i][0];
s->downmix_coef[i][1] = dca_default_coeffs[am][i][1];
}
}
av_dlog(s->avctx, "Stereo downmix coeffs:\n");
- for (i = 0; i < s->prim_channels + !!s->lfe; i++) {
+ for (i = 0; i < num_core_channels + !!s->lfe; i++) {
av_dlog(s->avctx, "L, input channel %d = %f\n", i,
s->downmix_coef[i][0]);
av_dlog(s->avctx, "R, input channel %d = %f\n", i,
for (i = 0; i < 2 * s->lfe * 4; i++)
s->lfe_data[i] = s->lfe_data[i + lfe_samples];
+ /* AVMatrixEncoding
+ *
+ * DCA_STEREO_TOTAL (Lt/Rt) is equivalent to Dolby Surround */
+ ret = ff_side_data_update_matrix_encoding(frame,
+ (s->output & ~DCA_LFE) == DCA_STEREO_TOTAL ?
+ AV_MATRIX_ENCODING_DOLBY : AV_MATRIX_ENCODING_NONE);
+ if (ret < 0)
+ return ret;
+
*got_frame_ptr = 1;
return buf_size;
{ FF_PROFILE_UNKNOWN },
};
+static const AVOption options[] = {
+ { "disable_xch", "disable decoding of the XCh extension", offsetof(DCAContext, xch_disable), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, AV_OPT_FLAG_DECODING_PARAM|AV_OPT_FLAG_AUDIO_PARAM },
+ { NULL },
+};
+
+static const AVClass dca_decoder_class = {
+ .class_name = "DCA decoder",
+ .item_name = av_default_item_name,
+ .option = options,
+ .version = LIBAVUTIL_VERSION_INT,
+};
+
AVCodec ff_dca_decoder = {
.name = "dca",
.long_name = NULL_IF_CONFIG_SMALL("DCA (DTS Coherent Acoustics)"),
.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP,
AV_SAMPLE_FMT_NONE },
.profiles = NULL_IF_CONFIG_SMALL(profiles),
+ .priv_class = &dca_decoder_class,
};