#include <stddef.h>
#include <stdio.h>
+#include "libavutil/channel_layout.h"
#include "libavutil/common.h"
#include "libavutil/float_dsp.h"
-#include "libavutil/intmath.h"
+#include "libavutil/internal.h"
#include "libavutil/intreadwrite.h"
#include "libavutil/mathematics.h"
-#include "libavutil/audioconvert.h"
+#include "libavutil/samplefmt.h"
#include "avcodec.h"
-#include "dsputil.h"
#include "fft.h"
#include "get_bits.h"
#include "put_bits.h"
#include "dcahuff.h"
#include "dca.h"
#include "dca_parser.h"
+#include "mathops.h"
#include "synth_filter.h"
#include "dcadsp.h"
#include "fmtconvert.h"
+#include "internal.h"
#if ARCH_ARM
# include "arm/dca.h"
typedef struct {
AVCodecContext *avctx;
- AVFrame frame;
/* Frame header */
int frame_type; ///< type of the current frame
int samples_deficit; ///< deficit sample count
/* Primary audio coding header */
int subframes; ///< number of subframes
- int is_channels_set; ///< check for if the channel number is already set
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
DECLARE_ALIGNED(32, float, raXin)[32];
int output; ///< type of output
- float scale_bias; ///< output scale
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];
+ float *samples_chanptr[DCA_PRIM_CHANNELS_MAX + 1];
+ float *extra_channels[DCA_PRIM_CHANNELS_MAX + 1];
+ uint8_t *extra_channels_buffer;
+ unsigned int extra_channels_buffer_size;
uint8_t dca_buffer[DCA_MAX_FRAME_SIZE + DCA_MAX_EXSS_HEADER_SIZE + DCA_BUFFER_PADDING_SIZE];
int dca_buffer_size; ///< how much data is in the dca_buffer
}
if (s->bitalloc[j][k] > 26) {
- // av_log(s->avctx, AV_LOG_DEBUG, "bitalloc index [%i][%i] too big (%i)\n",
- // j, k, s->bitalloc[j][k]);
+ av_dlog(s->avctx, "bitalloc index [%i][%i] too big (%i)\n",
+ j, k, s->bitalloc[j][k]);
return AVERROR_INVALIDDATA;
}
}
}
/* downmixing routines */
-#define MIX_REAR1(samples, si1, rs, coef) \
- samples[i] += samples[si1] * coef[rs][0]; \
- samples[i+256] += samples[si1] * coef[rs][1];
+#define MIX_REAR1(samples, s1, rs, coef) \
+ samples[0][i] += samples[s1][i] * coef[rs][0]; \
+ samples[1][i] += samples[s1][i] * coef[rs][1];
-#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_REAR2(samples, s1, s2, rs, coef) \
+ samples[0][i] += samples[s1][i] * coef[rs][0] + samples[s2][i] * coef[rs + 1][0]; \
+ samples[1][i] += samples[s1][i] * coef[rs][1] + samples[s2][i] * coef[rs + 1][1];
#define MIX_FRONT3(samples, coef) \
- t = samples[i + c]; \
- u = samples[i + l]; \
- v = samples[i + r]; \
- samples[i] = t * coef[0][0] + u * coef[1][0] + v * coef[2][0]; \
- samples[i+256] = t * coef[0][1] + u * coef[1][1] + v * coef[2][1];
+ t = samples[c][i]; \
+ u = samples[l][i]; \
+ v = samples[r][i]; \
+ samples[0][i] = t * coef[0][0] + u * coef[1][0] + v * coef[2][0]; \
+ samples[1][i] = t * coef[0][1] + u * coef[1][1] + v * 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],
const int8_t *channel_mapping)
{
case DCA_STEREO:
break;
case DCA_3F:
- c = channel_mapping[0] * 256;
- l = channel_mapping[1] * 256;
- r = channel_mapping[2] * 256;
+ c = channel_mapping[0];
+ l = channel_mapping[1];
+ r = channel_mapping[2];
DOWNMIX_TO_STEREO(MIX_FRONT3(samples, coef), );
break;
case DCA_2F1R:
- s = channel_mapping[2] * 256;
- DOWNMIX_TO_STEREO(MIX_REAR1(samples, i + s, 2, coef), );
+ s = channel_mapping[2];
+ DOWNMIX_TO_STEREO(MIX_REAR1(samples, s, 2, coef), );
break;
case DCA_3F1R:
- c = channel_mapping[0] * 256;
- l = channel_mapping[1] * 256;
- r = channel_mapping[2] * 256;
- s = channel_mapping[3] * 256;
+ c = channel_mapping[0];
+ l = channel_mapping[1];
+ r = channel_mapping[2];
+ s = channel_mapping[3];
DOWNMIX_TO_STEREO(MIX_FRONT3(samples, coef),
- MIX_REAR1(samples, i + s, 3, coef));
+ MIX_REAR1(samples, s, 3, coef));
break;
case DCA_2F2R:
- sl = channel_mapping[2] * 256;
- sr = channel_mapping[3] * 256;
- DOWNMIX_TO_STEREO(MIX_REAR2(samples, i + sl, i + sr, 2, coef), );
+ sl = channel_mapping[2];
+ sr = channel_mapping[3];
+ DOWNMIX_TO_STEREO(MIX_REAR2(samples, sl, sr, 2, coef), );
break;
case DCA_3F2R:
- c = channel_mapping[0] * 256;
- l = channel_mapping[1] * 256;
- r = channel_mapping[2] * 256;
- sl = channel_mapping[3] * 256;
- sr = channel_mapping[4] * 256;
+ c = channel_mapping[0];
+ l = channel_mapping[1];
+ r = channel_mapping[2];
+ sl = channel_mapping[3];
+ sr = channel_mapping[4];
DOWNMIX_TO_STEREO(MIX_FRONT3(samples, coef),
- MIX_REAR2(samples, i + sl, i + sr, 3, coef));
+ MIX_REAR2(samples, sl, sr, 3, coef));
break;
}
}
for (k = 0; k < s->prim_channels; k++) {
/* static float pcm_to_double[8] = { 32768.0, 32768.0, 524288.0, 524288.0,
0, 8388608.0, 8388608.0 };*/
- qmf_32_subbands(s, k, subband_samples[k],
- &s->samples[256 * s->channel_order_tab[k]],
- M_SQRT1_2 * s->scale_bias /* pcm_to_double[s->source_pcm_res] */);
+ if (s->channel_order_tab[k] >= 0)
+ qmf_32_subbands(s, k, subband_samples[k],
+ s->samples_chanptr[s->channel_order_tab[k]],
+ 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, s->amode, s->downmix_coef, s->channel_order_tab);
+ 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) {
lfe_interpolation_fir(s, s->lfe, 2 * s->lfe,
s->lfe_data + 2 * s->lfe * (block_index + 4),
- &s->samples[256 * dca_lfe_index[s->amode]],
- (1.0 / 256.0) * s->scale_bias);
+ s->samples_chanptr[dca_lfe_index[s->amode]],
+ 1.0 / (256.0 * 32768.0));
/* Outputs 20bits pcm samples */
}
num_audiop = get_bits(&s->gb, 3) + 1;
if (num_audiop > 1) {
- av_log_ask_for_sample(s->avctx, "Multiple DTS-HD audio presentations.");
+ avpriv_request_sample(s->avctx,
+ "Multiple DTS-HD audio presentations");
/* ignore such streams for now */
return;
}
num_assets = get_bits(&s->gb, 3) + 1;
if (num_assets > 1) {
- av_log_ask_for_sample(s->avctx, "Multiple DTS-HD audio assets.");
+ avpriv_request_sample(s->avctx, "Multiple DTS-HD audio assets");
/* ignore such streams for now */
return;
}
static int dca_decode_frame(AVCodecContext *avctx, void *data,
int *got_frame_ptr, AVPacket *avpkt)
{
+ AVFrame *frame = data;
const uint8_t *buf = avpkt->data;
int buf_size = avpkt->size;
int lfe_samples;
int num_core_channels = 0;
int i, ret;
- float *samples_flt;
- int16_t *samples_s16;
+ float **samples_flt;
DCAContext *s = avctx->priv_data;
- int channels;
+ int channels, full_channels;
int core_ss_end;
avctx->profile = s->profile;
- channels = s->prim_channels + !!s->lfe;
+ full_channels = channels = s->prim_channels + !!s->lfe;
if (s->amode < 16) {
avctx->channel_layout = dca_core_channel_layout[s->amode];
av_log(avctx, AV_LOG_ERROR, "Non standard configuration %d !\n", s->amode);
return AVERROR_INVALIDDATA;
}
-
-
- /* There is nothing that prevents a dts frame to change channel configuration
- but Libav 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 (s->is_channels_set == 0) {
- s->is_channels_set = 1;
- avctx->channels = channels;
- }
- if (avctx->channels != channels) {
- av_log(avctx, AV_LOG_ERROR, "DCA decoder does not support number of "
- "channels changing in stream. Skipping frame.\n");
- return AVERROR_PATCHWELCOME;
- }
+ avctx->channels = channels;
/* get output buffer */
- s->frame.nb_samples = 256 * (s->sample_blocks / 8);
- if ((ret = avctx->get_buffer(avctx, &s->frame)) < 0) {
+ frame->nb_samples = 256 * (s->sample_blocks / 8);
+ if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) {
av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
return ret;
}
- samples_flt = (float *) s->frame.data[0];
- samples_s16 = (int16_t *) s->frame.data[0];
+ samples_flt = (float **)frame->extended_data;
+
+ /* allocate buffer for extra channels if downmixing */
+ if (avctx->channels < full_channels) {
+ ret = av_samples_get_buffer_size(NULL, full_channels - channels,
+ frame->nb_samples,
+ avctx->sample_fmt, 0);
+ if (ret < 0)
+ return ret;
+
+ av_fast_malloc(&s->extra_channels_buffer,
+ &s->extra_channels_buffer_size, ret);
+ if (!s->extra_channels_buffer)
+ return AVERROR(ENOMEM);
+
+ ret = av_samples_fill_arrays((uint8_t **)s->extra_channels, NULL,
+ s->extra_channels_buffer,
+ full_channels - channels,
+ frame->nb_samples, avctx->sample_fmt, 0);
+ if (ret < 0)
+ return ret;
+ }
/* filter to get final output */
for (i = 0; i < (s->sample_blocks / 8); i++) {
+ int ch;
+
+ for (ch = 0; ch < channels; ch++)
+ s->samples_chanptr[ch] = samples_flt[ch] + i * 256;
+ for (; ch < full_channels; ch++)
+ s->samples_chanptr[ch] = s->extra_channels[ch - channels] + i * 256;
+
dca_filter_channels(s, i);
/* If this was marked as a DTS-ES stream we need to subtract back- */
/* channel from SL & SR to remove matrixed back-channel signal */
if ((s->source_pcm_res & 1) && s->xch_present) {
- float *back_chan = s->samples + s->channel_order_tab[s->xch_base_channel] * 256;
- float *lt_chan = s->samples + s->channel_order_tab[s->xch_base_channel - 2] * 256;
- float *rt_chan = s->samples + s->channel_order_tab[s->xch_base_channel - 1] * 256;
+ float *back_chan = s->samples_chanptr[s->channel_order_tab[s->xch_base_channel]];
+ float *lt_chan = s->samples_chanptr[s->channel_order_tab[s->xch_base_channel - 2]];
+ float *rt_chan = s->samples_chanptr[s->channel_order_tab[s->xch_base_channel - 1]];
s->fdsp.vector_fmac_scalar(lt_chan, back_chan, -M_SQRT1_2, 256);
s->fdsp.vector_fmac_scalar(rt_chan, back_chan, -M_SQRT1_2, 256);
}
-
- if (avctx->sample_fmt == AV_SAMPLE_FMT_FLT) {
- s->fmt_conv.float_interleave(samples_flt, s->samples_chanptr, 256,
- channels);
- samples_flt += 256 * channels;
- } else {
- s->fmt_conv.float_to_int16_interleave(samples_s16,
- s->samples_chanptr, 256,
- channels);
- samples_s16 += 256 * channels;
- }
}
/* update lfe history */
for (i = 0; i < 2 * s->lfe * 4; i++)
s->lfe_data[i] = s->lfe_data[i + lfe_samples];
- *got_frame_ptr = 1;
- *(AVFrame *) data = s->frame;
+ *got_frame_ptr = 1;
return buf_size;
}
static av_cold int dca_decode_init(AVCodecContext *avctx)
{
DCAContext *s = avctx->priv_data;
- int i;
s->avctx = avctx;
dca_init_vlcs();
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;
-
- if (avctx->request_sample_fmt == AV_SAMPLE_FMT_FLT) {
- avctx->sample_fmt = AV_SAMPLE_FMT_FLT;
- s->scale_bias = 1.0 / 32768.0;
- } else {
- avctx->sample_fmt = AV_SAMPLE_FMT_S16;
- s->scale_bias = 1.0;
- }
+ avctx->sample_fmt = AV_SAMPLE_FMT_FLTP;
/* allow downmixing to stereo */
if (avctx->channels > 0 && avctx->request_channels < avctx->channels &&
avctx->channels = avctx->request_channels;
}
- avcodec_get_frame_defaults(&s->frame);
- avctx->coded_frame = &s->frame;
-
return 0;
}
{
DCAContext *s = avctx->priv_data;
ff_mdct_end(&s->imdct);
+ av_freep(&s->extra_channels_buffer);
return 0;
}
.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_FLT,
- AV_SAMPLE_FMT_S16,
+ .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP,
AV_SAMPLE_FMT_NONE },
.profiles = NULL_IF_CONFIG_SMALL(profiles),
};