diff options
Diffstat (limited to 'ffmpeg/libavcodec/dcadec.c')
| -rw-r--r-- | ffmpeg/libavcodec/dcadec.c | 333 |
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, }; |
