summaryrefslogtreecommitdiff
path: root/ffmpeg/libavcodec/dcadec.c
diff options
context:
space:
mode:
authorTim Redfern <tim@eclectronics.org>2013-12-29 12:19:38 +0000
committerTim Redfern <tim@eclectronics.org>2013-12-29 12:19:38 +0000
commitf7813a5324be39d13ab536c245d15dfc602a7849 (patch)
treefad99148b88823d34a5df2f0a25881a002eb291b /ffmpeg/libavcodec/dcadec.c
parentb7a5a477b8ff4d4e3028b9dfb9a9df0a41463f92 (diff)
basic type mechanism working
Diffstat (limited to 'ffmpeg/libavcodec/dcadec.c')
-rw-r--r--ffmpeg/libavcodec/dcadec.c333
1 files changed, 228 insertions, 105 deletions
diff --git a/ffmpeg/libavcodec/dcadec.c b/ffmpeg/libavcodec/dcadec.c
index cf4412c..cc2fa0a 100644
--- a/ffmpeg/libavcodec/dcadec.c
+++ b/ffmpeg/libavcodec/dcadec.c
@@ -32,15 +32,14 @@
#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"
#include "get_bits.h"
-#include "put_bits.h"
#include "dcadata.h"
#include "dcahuff.h"
#include "dca.h"
-#include "dca_parser.h"
#include "mathops.h"
#include "synth_filter.h"
#include "dcadsp.h"
@@ -327,6 +326,8 @@ static const int8_t dca_channel_reorder_nolfe_xch[][9] = {
#define DCA_BUFFER_PADDING_SIZE 1024
+#define DCA_NSYNCAUX 0x9A1105A0
+
/** Bit allocation */
typedef struct {
int offset; ///< code values offset
@@ -348,6 +349,7 @@ static av_always_inline int get_bitalloc(GetBitContext *gb, BitAlloc *ba,
}
typedef struct {
+ const AVClass *class; ///< class for AVOptions
AVCodecContext *avctx;
/* Frame header */
int frame_type; ///< type of the current frame
@@ -360,7 +362,6 @@ typedef struct {
int bit_rate; ///< transmission bit rate
int bit_rate_index; ///< transmission bit rate index
- int downmix; ///< embedded downmix enabled
int dynrange; ///< embedded dynamic range flag
int timestamp; ///< embedded time stamp flag
int aux_data; ///< auxiliary data flag
@@ -402,9 +403,16 @@ typedef struct {
int 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
- int downmix_coef[DCA_PRIM_CHANNELS_MAX][2]; ///< stereo downmix coefficients
+ float downmix_coef[DCA_PRIM_CHANNELS_MAX + 1][2]; ///< stereo downmix coefficients
int dynrange_coef; ///< dynamic range coefficient
+ /* Core substream's embedded downmix coefficients (cf. ETSI TS 102 114 V1.4.1)
+ * Input: primary audio channels (incl. LFE if present)
+ * Output: downmix audio channels (up to 4, no LFE) */
+ uint8_t core_downmix; ///< embedded downmix coefficients available
+ 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
float lfe_data[2 * DCA_LFE_MAX * (DCA_BLOCKS_MAX + 4)]; ///< Low frequency effect data
@@ -439,6 +447,7 @@ typedef struct {
/* 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
/* XXCH extension information */
int xxch_chset;
@@ -591,7 +600,7 @@ static int dca_parse_audio_coding_header(DCAContext *s, int base_channel,
if (get_bits1(&s->gb)) {
embedded_downmix = get_bits1(&s->gb);
scale_factor =
- 1.0f / dca_downmix_scale_factors[(get_bits(&s->gb, 6) - 1) << 2];
+ 1.0f / dca_dmixtable[(get_bits(&s->gb, 6) - 1) << 2];
s->xxch_dmix_sf[s->xxch_chset] = scale_factor;
@@ -612,7 +621,7 @@ static int dca_parse_audio_coding_header(DCAContext *s, int base_channel,
coeff = get_bits(&s->gb, 7);
sign = (coeff & 64) ? 1.0 : -1.0;
- mag = dca_downmix_scale_factors[((coeff & 63) - 1) << 2];
+ mag = dca_dmixtable[((coeff & 63) - 1) << 2];
ichan = dca_xxch2index(s, 1 << i);
s->xxch_dmix_coeff[j][ichan] = sign * mag;
}
@@ -726,7 +735,7 @@ static int dca_parse_frame_header(DCAContext *s)
if (!s->bit_rate)
return AVERROR_INVALIDDATA;
- s->downmix = get_bits(&s->gb, 1); /* note: this is FixedBit == 0 */
+ skip_bits1(&s->gb); // always 0 (reserved, cf. ETSI TS 102 114 V1.4.1)
s->dynrange = get_bits(&s->gb, 1);
s->timestamp = get_bits(&s->gb, 1);
s->aux_data = get_bits(&s->gb, 1);
@@ -737,10 +746,10 @@ static int dca_parse_frame_header(DCAContext *s)
s->lfe = get_bits(&s->gb, 2);
s->predictor_history = get_bits(&s->gb, 1);
- if (s->lfe == 3) {
+ if (s->lfe > 2) {
s->lfe = 0;
- avpriv_request_sample(s->avctx, "LFE = 3");
- return AVERROR_PATCHWELCOME;
+ av_log(s->avctx, AV_LOG_ERROR, "Invalid LFE value: %d\n", s->lfe);
+ return AVERROR_INVALIDDATA;
}
/* TODO: check CRC */
@@ -773,7 +782,6 @@ static int dca_parse_frame_header(DCAContext *s)
s->sample_rate);
av_log(s->avctx, AV_LOG_DEBUG, "bit rate: %i bits/s\n",
s->bit_rate);
- av_log(s->avctx, AV_LOG_DEBUG, "downmix: %i\n", s->downmix);
av_log(s->avctx, AV_LOG_DEBUG, "dynrange: %i\n", s->dynrange);
av_log(s->avctx, AV_LOG_DEBUG, "timestamp: %i\n", s->timestamp);
av_log(s->avctx, AV_LOG_DEBUG, "aux_data: %i\n", s->aux_data);
@@ -956,27 +964,6 @@ static int dca_subframe_header(DCAContext *s, int base_channel, int block_index)
}
}
- /* Stereo downmix coefficients */
- if (!base_channel && s->prim_channels > 2) {
- if (s->downmix) {
- for (j = base_channel; 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;
- if (am >= FF_ARRAY_ELEMS(dca_default_coeffs)) {
- av_log(s->avctx, AV_LOG_ERROR,
- "Invalid channel mode %d\n", am);
- return AVERROR_INVALIDDATA;
- }
- for (j = base_channel; j < FFMIN(s->prim_channels, FF_ARRAY_ELEMS(dca_default_coeffs[am])); j++) {
- s->downmix_coef[j][0] = dca_default_coeffs[am][j][0];
- s->downmix_coef[j][1] = dca_default_coeffs[am][j][1];
- }
- }
- }
-
/* Dynamic range coefficient */
if (!base_channel && s->dynrange)
s->dynrange_coef = get_bits(&s->gb, 8);
@@ -1076,16 +1063,6 @@ static int dca_subframe_header(DCAContext *s, int base_channel, int block_index)
av_log(s->avctx, AV_LOG_DEBUG, "\n");
}
}
- if (!base_channel && s->prim_channels > 2 && s->downmix) {
- av_log(s->avctx, AV_LOG_DEBUG, "Downmix coeffs:\n");
- for (j = 0; j < s->prim_channels; j++) {
- av_log(s->avctx, AV_LOG_DEBUG, "Channel 0, %d = %f\n", j,
- dca_downmix_coeffs[s->downmix_coef[j][0]]);
- av_log(s->avctx, AV_LOG_DEBUG, "Channel 1, %d = %f\n", j,
- dca_downmix_coeffs[s->downmix_coef[j][1]]);
- }
- av_log(s->avctx, AV_LOG_DEBUG, "\n");
- }
for (j = base_channel; j < s->prim_channels; j++)
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]);
@@ -1108,10 +1085,8 @@ static void qmf_32_subbands(DCAContext *s, int chans,
float scale)
{
const float *prCoeff;
- int i;
int sb_act = s->subband_activity[chans];
- int subindex;
scale *= sqrt(1 / 8.0);
@@ -1121,25 +1096,11 @@ static void qmf_32_subbands(DCAContext *s, int chans,
else /* Perfect reconstruction */
prCoeff = fir_32bands_perfect;
- for (i = sb_act; i < 32; i++)
- s->raXin[i] = 0.0;
-
- /* Reconstructed channel sample index */
- for (subindex = 0; subindex < 8; subindex++) {
- /* Load in one sample from each subband and clear inactive subbands */
- for (i = 0; i < sb_act; i++) {
- unsigned sign = (i - 1) & 2;
- uint32_t v = AV_RN32A(&samples_in[i][subindex]) ^ sign << 30;
- AV_WN32A(&s->raXin[i], v);
- }
-
- s->synth.synth_filter_float(&s->imdct,
- s->subband_fir_hist[chans],
- &s->hist_index[chans],
- s->subband_fir_noidea[chans], prCoeff,
- samples_out, s->raXin, scale);
- samples_out += 32;
- }
+ s->dcadsp.qmf_32_subbands(samples_in, sb_act, &s->synth, &s->imdct,
+ s->subband_fir_hist[chans],
+ &s->hist_index[chans],
+ s->subband_fir_noidea[chans], prCoeff,
+ samples_out, s->raXin, scale);
}
static void lfe_interpolation_fir(DCAContext *s, int decimation_select,
@@ -1196,29 +1157,23 @@ static void lfe_interpolation_fir(DCAContext *s, int decimation_select,
op2 \
}
-static void dca_downmix(float **samples, int srcfmt,
- int downmix_coef[DCA_PRIM_CHANNELS_MAX][2],
+static void dca_downmix(float **samples, int srcfmt, int lfe_present,
+ float coef[DCA_PRIM_CHANNELS_MAX + 1][2],
const int8_t *channel_mapping)
{
int c, l, r, sl, sr, s;
int i;
float t, u, v;
- 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_CHANNEL:
- case DCA_STEREO_TOTAL:
- case DCA_STEREO_SUMDIFF:
case DCA_4F2R:
av_log(NULL, AV_LOG_ERROR, "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];
@@ -1253,13 +1208,21 @@ static void dca_downmix(float **samples, int srcfmt,
MIX_REAR2(samples, sl, sr, 3, coef));
break;
}
+ if (lfe_present) {
+ int lf_buf = dca_lfe_index[srcfmt];
+ int lf_idx = dca_channels [srcfmt];
+ for (i = 0; i < 256; i++) {
+ samples[0][i] += samples[lf_buf][i] * coef[lf_idx][0];
+ samples[1][i] += samples[lf_buf][i] * coef[lf_idx][1];
+ }
+ }
}
#ifndef decode_blockcodes
/* Very compact version of the block code decoder that does not use table
* look-up but is slightly slower */
-static int decode_blockcode(int code, int levels, int *values)
+static int decode_blockcode(int code, int levels, int32_t *values)
{
int i;
int offset = (levels - 1) >> 1;
@@ -1273,7 +1236,7 @@ static int decode_blockcode(int code, int levels, int *values)
return code;
}
-static int decode_blockcodes(int code1, int code2, int levels, int *values)
+static int decode_blockcodes(int code1, int code2, int levels, int32_t *values)
{
return decode_blockcode(code1, levels, values) |
decode_blockcode(code2, levels, values + 4);
@@ -1302,7 +1265,7 @@ static int dca_subsubframe(DCAContext *s, int base_channel, int block_index)
/* FIXME */
float (*subband_samples)[DCA_SUBBANDS][8] = s->subband_samples[block_index];
- LOCAL_ALIGNED_16(int, block, [8]);
+ LOCAL_ALIGNED_16(int32_t, block, [8 * DCA_SUBBANDS]);
/*
* Audio data
@@ -1315,6 +1278,8 @@ static int dca_subsubframe(DCAContext *s, int base_channel, int block_index)
quant_step_table = lossy_quant_d;
for (k = base_channel; k < s->prim_channels; k++) {
+ float rscale[DCA_SUBBANDS];
+
if (get_bits_left(&s->gb) < 0)
return AVERROR_INVALIDDATA;
@@ -1337,11 +1302,12 @@ static int dca_subsubframe(DCAContext *s, int base_channel, int block_index)
* Extract bits from the bit stream
*/
if (!abits) {
- memset(subband_samples[k][l], 0, 8 * sizeof(subband_samples[0][0][0]));
+ rscale[l] = 0;
+ memset(block + 8 * l, 0, 8 * sizeof(block[0]));
} else {
/* Deal with transients */
int sfi = s->transition_mode[k][l] && subsubframe >= s->transition_mode[k][l];
- float rscale = quant_step_size * s->scale_factor[k][l][sfi] *
+ rscale[l] = quant_step_size * s->scale_factor[k][l][sfi] *
s->scalefactor_adj[k][sel];
if (abits >= 11 || !dca_smpl_bitalloc[abits].vlc[sel].table) {
@@ -1355,7 +1321,7 @@ static int dca_subsubframe(DCAContext *s, int base_channel, int block_index)
block_code1 = get_bits(&s->gb, size);
block_code2 = get_bits(&s->gb, size);
err = decode_blockcodes(block_code1, block_code2,
- levels, block);
+ levels, block + 8 * l);
if (err) {
av_log(s->avctx, AV_LOG_ERROR,
"ERROR: block code look-up failed\n");
@@ -1364,19 +1330,23 @@ static int dca_subsubframe(DCAContext *s, int base_channel, int block_index)
} else {
/* no coding */
for (m = 0; m < 8; m++)
- block[m] = get_sbits(&s->gb, abits - 3);
+ block[8 * l + m] = get_sbits(&s->gb, abits - 3);
}
} else {
/* Huffman coded */
for (m = 0; m < 8; m++)
- block[m] = get_bitalloc(&s->gb,
+ block[8 * l + m] = get_bitalloc(&s->gb,
&dca_smpl_bitalloc[abits], sel);
}
- s->fmt_conv.int32_to_float_fmul_scalar(subband_samples[k][l],
- block, rscale, 8);
}
+ }
+
+ s->fmt_conv.int32_to_float_fmul_array8(&s->fmt_conv, subband_samples[k][0],
+ block, rscale, 8 * s->vq_start_subband[k]);
+ for (l = 0; l < s->vq_start_subband[k]; l++) {
+ int m;
/*
* Inverse ADPCM if in prediction mode
*/
@@ -1424,6 +1394,7 @@ static int dca_subsubframe(DCAContext *s, int base_channel, int block_index)
#endif
} else {
av_log(s->avctx, AV_LOG_ERROR, "Didn't get subframe DSYNC\n");
+ return AVERROR_INVALIDDATA;
}
}
@@ -1452,13 +1423,8 @@ static int dca_filter_channels(DCAContext *s, int block_index)
M_SQRT1_2 / 32768.0 /* pcm_to_double[s->source_pcm_res] */);
}
- /* Down mixing */
- if (s->avctx->request_channels == 2 && s->prim_channels > 2) {
- dca_downmix(s->samples_chanptr, s->amode, s->downmix_coef, s->channel_order_tab);
- }
-
/* 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[s->lfe_index],
@@ -1466,13 +1432,21 @@ static int dca_filter_channels(DCAContext *s, int block_index)
/* Outputs 20bits pcm samples */
}
+ /* Downmixing to Stereo */
+ if (s->prim_channels + !!s->lfe > 2 &&
+ s->avctx->request_channel_layout == AV_CH_LAYOUT_STEREO) {
+ dca_downmix(s->samples_chanptr, s->amode, !!s->lfe, s->downmix_coef,
+ s->channel_order_tab);
+ }
+
return 0;
}
static int dca_subframe_footer(DCAContext *s, int base_channel)
{
- int aux_data_count = 0, i;
+ int in, out, aux_data_count, aux_data_end, reserved;
+ uint32_t nsyncaux;
/*
* Unpack optional information
@@ -1483,13 +1457,89 @@ static int dca_subframe_footer(DCAContext *s, int base_channel)
if (s->timestamp)
skip_bits_long(&s->gb, 32);
- if (s->aux_data)
+ if (s->aux_data) {
aux_data_count = get_bits(&s->gb, 6);
- for (i = 0; i < aux_data_count; i++)
- get_bits(&s->gb, 8);
+ // align (32-bit)
+ skip_bits_long(&s->gb, (-get_bits_count(&s->gb)) & 31);
+
+ aux_data_end = 8 * aux_data_count + get_bits_count(&s->gb);
+
+ 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,
+ "Auxiliary Decode Time Stamp Flag");
+ // align (4-bit)
+ skip_bits(&s->gb, (-get_bits_count(&s->gb)) & 4);
+ // 44 bits: nMSByte (8), nMarker (4), nLSByte (28), nMarker (4)
+ skip_bits_long(&s->gb, 44);
+ }
+
+ if ((s->core_downmix = get_bits1(&s->gb))) {
+ int am = get_bits(&s->gb, 3);
+ switch (am) {
+ case 0:
+ s->core_downmix_amode = DCA_MONO;
+ break;
+ case 1:
+ s->core_downmix_amode = DCA_STEREO;
+ break;
+ case 2:
+ s->core_downmix_amode = DCA_STEREO_TOTAL;
+ break;
+ case 3:
+ s->core_downmix_amode = DCA_3F;
+ break;
+ case 4:
+ s->core_downmix_amode = DCA_2F1R;
+ break;
+ case 5:
+ s->core_downmix_amode = DCA_2F2R;
+ break;
+ case 6:
+ 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) {
+ av_log(s->avctx, AV_LOG_ERROR,
+ "Invalid downmix coefficient code %"PRIu16"\n",
+ tmp);
+ return AVERROR_INVALIDDATA;
+ }
+ s->core_downmix_codes[in][out] = tmp;
+ }
+ }
+ }
+
+ align_get_bits(&s->gb); // byte align
+ 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) {
+ av_log(s->avctx, AV_LOG_ERROR,
+ "Overread auxiliary data by %d bits\n", -reserved);
+ return AVERROR_INVALIDDATA;
+ } else if (reserved) {
+ avpriv_request_sample(s->avctx,
+ "Core auxiliary data reserved content");
+ skip_bits_long(&s->gb, reserved);
+ }
+ }
- if (s->crc_present && (s->downmix || s->dynrange))
+ if (s->crc_present && s->dynrange)
get_bits(&s->gb, 16);
}
@@ -2120,6 +2170,54 @@ static int dca_decode_frame(AVCodecContext *avctx, void *data,
/* 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)) {
+ 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]);
+ }
+ } else {
+ int am = s->amode & DCA_CHANNEL_MASK;
+ if (am >= FF_ARRAY_ELEMS(dca_default_coeffs)) {
+ av_log(s->avctx, AV_LOG_ERROR,
+ "Invalid channel mode %d\n", am);
+ return AVERROR_INVALIDDATA;
+ }
+ if (s->prim_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++) {
+ 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++) {
+ 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,
+ s->downmix_coef[i][1]);
+ }
+ av_dlog(s->avctx, "\n");
+ }
+
if (s->ext_coding)
s->core_ext_mask = dca_ext_audio_descr_mask[s->ext_descr];
else
@@ -2237,10 +2335,15 @@ static int dca_decode_frame(AVCodecContext *avctx, void *data,
{ /* xxx should also do MA extensions */
if (s->amode < 16) {
avctx->channel_layout = dca_core_channel_layout[s->amode];
-
- if (s->xch_present && (!avctx->request_channels ||
- avctx->request_channels
- > num_core_channels + !!s->lfe)) {
+#if FF_API_REQUEST_CHANNELS
+FF_DISABLE_DEPRECATION_WARNINGS
+ 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 && !s->xch_disable) {
+#endif
avctx->channel_layout |= AV_CH_BACK_CENTER;
if (s->lfe) {
avctx->channel_layout |= AV_CH_LOW_FREQUENCY;
@@ -2269,7 +2372,8 @@ static int dca_decode_frame(AVCodecContext *avctx, void *data,
return AVERROR_INVALIDDATA;
}
- if (avctx->request_channels == 2 && s->prim_channels > 2) {
+ if (s->prim_channels + !!s->lfe > 2 &&
+ avctx->request_channel_layout == AV_CH_LAYOUT_STEREO) {
channels = 2;
s->output = DCA_STEREO;
avctx->channel_layout = AV_CH_LAYOUT_STEREO;
@@ -2484,10 +2588,15 @@ static av_cold int dca_decode_init(AVCodecContext *avctx)
avctx->sample_fmt = AV_SAMPLE_FMT_FLTP;
/* allow downmixing to stereo */
- if (avctx->channels > 0 && avctx->request_channels < avctx->channels &&
- avctx->request_channels == 2) {
- avctx->channels = avctx->request_channels;
- }
+#if FF_API_REQUEST_CHANNELS
+FF_DISABLE_DEPRECATION_WARNINGS
+ if (avctx->request_channels == 2)
+ avctx->request_channel_layout = AV_CH_LAYOUT_STEREO;
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+ if (avctx->channels > 2 &&
+ avctx->request_channel_layout == AV_CH_LAYOUT_STEREO)
+ avctx->channels = 2;
return 0;
}
@@ -2509,17 +2618,31 @@ static const AVProfile profiles[] = {
{ 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,
+ .category = AV_CLASS_CATEGORY_DECODER,
+};
+
AVCodec ff_dca_decoder = {
.name = "dca",
+ .long_name = NULL_IF_CONFIG_SMALL("DCA (DTS Coherent Acoustics)"),
.type = AVMEDIA_TYPE_AUDIO,
.id = AV_CODEC_ID_DTS,
.priv_data_size = sizeof(DCAContext),
.init = dca_decode_init,
.decode = dca_decode_frame,
.close = dca_decode_end,
- .long_name = NULL_IF_CONFIG_SMALL("DCA (DTS Coherent Acoustics)"),
.capabilities = CODEC_CAP_CHANNEL_CONF | CODEC_CAP_DR1,
.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP,
AV_SAMPLE_FMT_NONE },
.profiles = NULL_IF_CONFIG_SMALL(profiles),
+ .priv_class = &dca_decoder_class,
};