#include "libavutil/common.h"
#include "libavutil/intmath.h"
#include "libavutil/intreadwrite.h"
-#include "libavcore/audioconvert.h"
+#include "libavutil/audioconvert.h"
#include "avcodec.h"
#include "dsputil.h"
#include "fft.h"
#include "dca.h"
#include "synth_filter.h"
#include "dcadsp.h"
+#include "fmtconvert.h"
//#define TRACE
DCA_EXT_EXSS_XLL = 0x200, ///< lossless extension in ExSS
};
+/* -1 are reserved or unknown */
+static const int dca_ext_audio_descr_mask[] = {
+ DCA_EXT_XCH,
+ -1,
+ DCA_EXT_X96,
+ DCA_EXT_XCH | DCA_EXT_X96,
+ -1,
+ -1,
+ DCA_EXT_XXCH,
+ -1,
+};
+
+/* extensions that reside in core substream */
+#define DCA_CORE_EXTS (DCA_EXT_XCH | DCA_EXT_XXCH | DCA_EXT_X96)
+
/* Tables for mapping dts channel configurations to libavcodec multichannel api.
* Some compromises have been made for special configurations. Most configurations
* are never used so complete accuracy is not needed.
* L = left, R = right, C = center, S = surround, F = front, R = rear, T = total, OV = overhead.
* S -> side, when both rear and back are configured move one of them to the side channel
* OV -> center back
- * All 2 channel configurations -> CH_LAYOUT_STEREO
+ * All 2 channel configurations -> AV_CH_LAYOUT_STEREO
*/
static const int64_t dca_core_channel_layout[] = {
AV_CH_LAYOUT_STEREO, ///< 2, LT +RT (left and right total)
AV_CH_LAYOUT_STEREO|AV_CH_FRONT_CENTER, ///< 3, C+L+R
AV_CH_LAYOUT_STEREO|AV_CH_BACK_CENTER, ///< 3, L+R+S
- AV_CH_LAYOUT_STEREO|AV_CH_FRONT_CENTER|CH_BACK_CENTER, ///< 4, C + L + R+ S
+ AV_CH_LAYOUT_STEREO|AV_CH_FRONT_CENTER|AV_CH_BACK_CENTER, ///< 4, C + L + R+ S
AV_CH_LAYOUT_STEREO|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT, ///< 4, L + R +SL+ SR
AV_CH_LAYOUT_STEREO|AV_CH_FRONT_CENTER|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT, ///< 5, C + L + R+ SL+SR
AV_CH_LAYOUT_STEREO|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER, ///< 6, CL + CR + L + R + SL + SR
/* Subband samples history (for ADPCM) */
float subband_samples_hist[DCA_PRIM_CHANNELS_MAX][DCA_SUBBANDS][4];
- DECLARE_ALIGNED(16, float, subband_fir_hist)[DCA_PRIM_CHANNELS_MAX][512];
- DECLARE_ALIGNED(16, float, subband_fir_noidea)[DCA_PRIM_CHANNELS_MAX][32];
+ DECLARE_ALIGNED(32, float, subband_fir_hist)[DCA_PRIM_CHANNELS_MAX][512];
+ DECLARE_ALIGNED(32, float, subband_fir_noidea)[DCA_PRIM_CHANNELS_MAX][32];
int hist_index[DCA_PRIM_CHANNELS_MAX];
- DECLARE_ALIGNED(16, float, raXin)[32];
+ DECLARE_ALIGNED(32, float, raXin)[32];
int output; ///< type of output
float scale_bias; ///< output scale
- DECLARE_ALIGNED(16, float, subband_samples)[DCA_BLOCKS_MAX][DCA_PRIM_CHANNELS_MAX][DCA_SUBBANDS][8];
- DECLARE_ALIGNED(16, float, samples)[(DCA_PRIM_CHANNELS_MAX+1)*256];
+ DECLARE_ALIGNED(32, float, subband_samples)[DCA_BLOCKS_MAX][DCA_PRIM_CHANNELS_MAX][DCA_SUBBANDS][8];
+ DECLARE_ALIGNED(32, float, samples)[(DCA_PRIM_CHANNELS_MAX+1)*256];
const float *samples_chanptr[DCA_PRIM_CHANNELS_MAX+1];
uint8_t dca_buffer[DCA_MAX_FRAME_SIZE + DCA_MAX_EXSS_HEADER_SIZE + DCA_BUFFER_PADDING_SIZE];
int current_subframe;
int current_subsubframe;
+ int core_ext_mask; ///< present extensions in the core substream
+
/* XCh extension information */
- int xch_present;
+ int xch_present; ///< XCh extension present and valid
int xch_base_channel; ///< index of first (only) channel containing XCH data
- /* Other detected extensions in the core substream */
- int xxch_present;
- int x96_present;
-
/* ExSS header parser */
int static_fields; ///< static fields present
int mix_metadata; ///< mixing metadata present
FFTContext imdct;
SynthFilterContext synth;
DCADSPContext dcadsp;
+ FmtConvertContext fmt_conv;
} DCAContext;
static const uint16_t dca_vlc_offs[] = {
block[m] = get_bitalloc(&s->gb, &dca_smpl_bitalloc[abits], sel);
}
- s->dsp.int32_to_float_fmul_scalar(subband_samples[k][l],
+ s->fmt_conv.int32_to_float_fmul_scalar(subband_samples[k][l],
block, rscale, 8);
}
if (!(extensions_mask & DCA_EXT_CORE))
av_log(s->avctx, AV_LOG_WARNING, "DTS core detection mismatch.\n");
- if (!!(extensions_mask & DCA_EXT_XCH) != s->xch_present)
- av_log(s->avctx, AV_LOG_WARNING, "DTS XCh detection mismatch.\n");
- if (!!(extensions_mask & DCA_EXT_XXCH) != s->xxch_present)
- av_log(s->avctx, AV_LOG_WARNING, "DTS XXCh detection mismatch.\n");
- if (!!(extensions_mask & DCA_EXT_X96) != s->x96_present)
- av_log(s->avctx, AV_LOG_WARNING, "DTS X96 detection mismatch.\n");
+ if ((extensions_mask & DCA_CORE_EXTS) != s->core_ext_mask)
+ av_log(s->avctx, AV_LOG_WARNING, "DTS extensions detection mismatch (%d, %d)\n",
+ extensions_mask & DCA_CORE_EXTS, s->core_ext_mask);
return 0;
}
int lfe_samples;
int num_core_channels = 0;
int i;
+ float *samples_flt = data;
int16_t *samples = data;
DCAContext *s = avctx->priv_data;
int channels;
s->xch_present = 0;
- s->x96_present = 0;
- s->xxch_present = 0;
s->dca_buffer_size = dca_convert_bitstream(buf, buf_size, s->dca_buffer,
DCA_MAX_FRAME_SIZE + DCA_MAX_EXSS_HEADER_SIZE);
/* record number of core channels incase less than max channels are requested */
num_core_channels = s->prim_channels;
- /* extensions start at 32-bit boundaries into bitstream */
- skip_bits_long(&s->gb, (-get_bits_count(&s->gb)) & 31);
+ if (s->ext_coding)
+ s->core_ext_mask = dca_ext_audio_descr_mask[s->ext_descr];
+ else
+ s->core_ext_mask = 0;
core_ss_end = FFMIN(s->frame_size, s->dca_buffer_size) * 8;
+ /* only scan for extensions if ext_descr was unknown or indicated a
+ * supported XCh extension */
+ if (s->core_ext_mask < 0 || s->core_ext_mask & DCA_EXT_XCH) {
+
+ /* if ext_descr was unknown, clear s->core_ext_mask so that the
+ * extensions scan can fill it up */
+ s->core_ext_mask = FFMAX(s->core_ext_mask, 0);
+
+ /* extensions start at 32-bit boundaries into bitstream */
+ skip_bits_long(&s->gb, (-get_bits_count(&s->gb)) & 31);
+
while(core_ss_end - get_bits_count(&s->gb) >= 32) {
uint32_t bits = get_bits_long(&s->gb, 32);
/* skip length-to-end-of-frame field for the moment */
skip_bits(&s->gb, 10);
- s->profile = FFMAX(s->profile, FF_PROFILE_DTS_ES);
+ s->core_ext_mask |= DCA_EXT_XCH;
/* extension amode should == 1, number of channels in extension */
/* AFAIK XCh is not used for more channels */
/* XXCh: extended channels */
/* usually found either in core or HD part in DTS-HD HRA streams,
* but not in DTS-ES which contains XCh extensions instead */
- s->xxch_present = 1;
- s->profile = FFMAX(s->profile, FF_PROFILE_DTS_ES);
+ s->core_ext_mask |= DCA_EXT_XXCH;
break;
case 0x1d95f262: {
av_log(avctx, AV_LOG_DEBUG, "FSIZE96 = %d bytes\n", fsize96);
av_log(avctx, AV_LOG_DEBUG, "REVNO = %d\n", get_bits(&s->gb, 4));
- s->x96_present = 1;
- s->profile = FFMAX(s->profile, FF_PROFILE_DTS_96_24);
+ s->core_ext_mask |= DCA_EXT_X96;
break;
}
}
skip_bits_long(&s->gb, (-get_bits_count(&s->gb)) & 31);
}
+ } else {
+ /* no supported extensions, skip the rest of the core substream */
+ skip_bits_long(&s->gb, core_ss_end - get_bits_count(&s->gb));
+ }
+
+ if (s->core_ext_mask & DCA_EXT_X96)
+ s->profile = FF_PROFILE_DTS_96_24;
+ else if (s->core_ext_mask & (DCA_EXT_XCH | DCA_EXT_XXCH))
+ s->profile = FF_PROFILE_DTS_ES;
+
/* check for ExSS (HD part) */
if (s->dca_buffer_size - s->frame_size > 32
&& get_bits_long(&s->gb, 32) == DCA_HD_MARKER)
return -1;
}
- if (*data_size < (s->sample_blocks / 8) * 256 * sizeof(int16_t) * channels)
+ /* ffdshow custom code */
+ if (*data_size < (s->sample_blocks / 8) * 256 * sizeof(samples[0]) * channels)
return -1;
- *data_size = 256 / 8 * s->sample_blocks * sizeof(int16_t) * channels;
+ *data_size = 256 / 8 * s->sample_blocks * sizeof(samples[0]) * channels;
/* filter to get final output */
for (i = 0; i < (s->sample_blocks / 8); i++) {
}
}
- s->dsp.float_to_int16_interleave(samples, s->samples_chanptr, 256, channels);
- samples += 256 * channels;
+ /* interleave samples */
+ if (avctx->sample_fmt == AV_SAMPLE_FMT_FLT) {
+ float_interleave(samples_flt, s->samples_chanptr, 256, channels);
+ samples_flt += 256 * channels;
+ } else {
+ s->fmt_conv.float_to_int16_interleave(samples, s->samples_chanptr, 256, channels);
+ samples += 256 * channels;
+ }
}
/* update lfe history */
ff_mdct_init(&s->imdct, 6, 1, 1.0);
ff_synth_filter_init(&s->synth);
ff_dcadsp_init(&s->dcadsp);
+ ff_fmt_convert_init(&s->fmt_conv, avctx);
for (i = 0; i < DCA_PRIM_CHANNELS_MAX+1; i++)
s->samples_chanptr[i] = s->samples + i * 256;
- avctx->sample_fmt = AV_SAMPLE_FMT_S16;
+ avctx->sample_fmt = avctx->request_sample_fmt == AV_SAMPLE_FMT_FLT ?
+ AV_SAMPLE_FMT_FLT : AV_SAMPLE_FMT_S16;
s->scale_bias = 1.0;