1
0
mirror of https://github.com/FFmpeg/FFmpeg.git synced 2024-12-23 12:43:46 +02:00

avcodec/dca: add new decoder based on libdcadec

This commit is contained in:
foo86 2016-01-16 11:54:38 +03:00 committed by Hendrik Leppkes
parent 0930b2dd1f
commit ae5b2c5250
22 changed files with 6085 additions and 16 deletions

View File

@ -61,6 +61,7 @@ version <next>:
- support for dvaudio in wav and avi
- libaacplus and libvo-aacenc support removed
- Cineform HD decoder
- new DCA decoder with full support for DTS-HD extensions
version 2.8:

1
configure vendored
View File

@ -2271,6 +2271,7 @@ comfortnoise_encoder_select="lpc"
cook_decoder_select="audiodsp mdct sinewin"
cscd_decoder_select="lzo"
cscd_decoder_suggest="zlib"
dca_decoder_select="mdct"
dds_decoder_select="texturedsp"
dirac_decoder_select="dirac_parse dwt golomb videodsp mpegvideoenc"
dnxhd_decoder_select="blockdsp idctdsp"

View File

@ -222,6 +222,9 @@ OBJS-$(CONFIG_COMFORTNOISE_ENCODER) += cngenc.o
OBJS-$(CONFIG_CPIA_DECODER) += cpia.o
OBJS-$(CONFIG_CSCD_DECODER) += cscd.o
OBJS-$(CONFIG_CYUV_DECODER) += cyuv.o
OBJS-$(CONFIG_DCA_DECODER) += dcadec.o dca.o dcadata.o \
dca_core.o dca_exss.o dca_xll.o \
dcadsp.o dcadct.o synth_filter.o
OBJS-$(CONFIG_DCA_ENCODER) += dcaenc.o dca.o dcadata.o
OBJS-$(CONFIG_DDS_DECODER) += dds.o
OBJS-$(CONFIG_DIRAC_DECODER) += diracdec.o dirac.o diracdsp.o \

View File

@ -1,4 +1,4 @@
#OBJS-$(CONFIG_DCA_DECODER) += aarch64/synth_filter_init.o
OBJS-$(CONFIG_DCA_DECODER) += aarch64/synth_filter_init.o
OBJS-$(CONFIG_FFT) += aarch64/fft_init_aarch64.o
OBJS-$(CONFIG_FMTCONVERT) += aarch64/fmtconvert_init.o
OBJS-$(CONFIG_H264CHROMA) += aarch64/h264chroma_init_aarch64.o
@ -17,7 +17,7 @@ OBJS-$(CONFIG_VORBIS_DECODER) += aarch64/vorbisdsp_init.o
ARMV8-OBJS-$(CONFIG_VIDEODSP) += aarch64/videodsp.o
#NEON-OBJS-$(CONFIG_DCA_DECODER) += aarch64/synth_filter_neon.o
NEON-OBJS-$(CONFIG_DCA_DECODER) += aarch64/synth_filter_neon.o
NEON-OBJS-$(CONFIG_FFT) += aarch64/fft_neon.o
NEON-OBJS-$(CONFIG_FMTCONVERT) += aarch64/fmtconvert_neon.o
NEON-OBJS-$(CONFIG_H264CHROMA) += aarch64/h264cmc_neon.o

View File

@ -391,7 +391,7 @@ void avcodec_register_all(void)
REGISTER_DECODER(BINKAUDIO_RDFT, binkaudio_rdft);
REGISTER_DECODER(BMV_AUDIO, bmv_audio);
REGISTER_DECODER(COOK, cook);
REGISTER_ENCODER(DCA, dca);
REGISTER_ENCDEC (DCA, dca);
REGISTER_DECODER(DSD_LSBF, dsd_lsbf);
REGISTER_DECODER(DSD_MSBF, dsd_msbf);
REGISTER_DECODER(DSD_LSBF_PLANAR, dsd_lsbf_planar);

View File

@ -36,7 +36,7 @@ OBJS-$(CONFIG_VP8DSP) += arm/vp8dsp_init_arm.o
# decoders/encoders
OBJS-$(CONFIG_AAC_DECODER) += arm/aacpsdsp_init_arm.o \
arm/sbrdsp_init_arm.o
#OBJS-$(CONFIG_DCA_DECODER) += arm/synth_filter_init_arm.o
OBJS-$(CONFIG_DCA_DECODER) += arm/synth_filter_init_arm.o
OBJS-$(CONFIG_HEVC_DECODER) += arm/hevcdsp_init_arm.o
OBJS-$(CONFIG_MLP_DECODER) += arm/mlpdsp_init_arm.o
OBJS-$(CONFIG_RV40_DECODER) += arm/rv40dsp_init_arm.o
@ -87,7 +87,7 @@ VFP-OBJS-$(CONFIG_FMTCONVERT) += arm/fmtconvert_vfp.o
VFP-OBJS-$(CONFIG_MDCT) += arm/mdct_vfp.o
# decoders/encoders
#VFP-OBJS-$(CONFIG_DCA_DECODER) += arm/synth_filter_vfp.o
VFP-OBJS-$(CONFIG_DCA_DECODER) += arm/synth_filter_vfp.o
# NEON optimizations
@ -126,7 +126,7 @@ NEON-OBJS-$(CONFIG_VP8DSP) += arm/vp8dsp_init_neon.o \
NEON-OBJS-$(CONFIG_AAC_DECODER) += arm/aacpsdsp_neon.o \
arm/sbrdsp_neon.o
NEON-OBJS-$(CONFIG_LLAUDDSP) += arm/lossless_audiodsp_neon.o
#NEON-OBJS-$(CONFIG_DCA_DECODER) += arm/synth_filter_neon.o
NEON-OBJS-$(CONFIG_DCA_DECODER) += arm/synth_filter_neon.o
NEON-OBJS-$(CONFIG_HEVC_DECODER) += arm/hevcdsp_init_neon.o \
arm/hevcdsp_deblock_neon.o \
arm/hevcdsp_idct_neon.o \

2603
libavcodec/dca_core.c Normal file

File diff suppressed because it is too large Load Diff

206
libavcodec/dca_core.h Normal file
View File

@ -0,0 +1,206 @@
/*
* Copyright (C) 2016 foo86
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVCODEC_DCA_CORE_H
#define AVCODEC_DCA_CORE_H
#include "libavutil/common.h"
#include "libavutil/float_dsp.h"
#include "libavutil/fixed_dsp.h"
#include "libavutil/mem.h"
#include "avcodec.h"
#include "internal.h"
#include "get_bits.h"
#include "dca.h"
#include "dca_exss.h"
#include "dcadsp.h"
#include "dcadct.h"
#include "fft.h"
#include "synth_filter.h"
#define DCA_CHANNELS 7
#define DCA_SUBBANDS 32
#define DCA_SUBBANDS_X96 64
#define DCA_SUBFRAMES 16
#define DCA_SUBBAND_SAMPLES 8
#define DCA_PCMBLOCK_SAMPLES 32
#define DCA_ADPCM_COEFFS 4
#define DCA_LFE_HISTORY 8
#define DCA_CODE_BOOKS 10
#define DCA_ABITS_MAX 26
#define DCA_CORE_CHANNELS_MAX 6
#define DCA_DMIX_CHANNELS_MAX 4
#define DCA_XXCH_CHANNELS_MAX 2
#define DCA_EXSS_CHANNELS_MAX 8
#define DCA_EXSS_CHSETS_MAX 4
#define DCA_FILTER_MODE_X96 0x01
#define DCA_FILTER_MODE_FIXED 0x02
typedef struct DCADSPData {
union {
struct {
DECLARE_ALIGNED(32, float, hist1)[1024];
DECLARE_ALIGNED(32, float, hist2)[64];
} flt;
struct {
DECLARE_ALIGNED(32, int32_t, hist1)[1024];
DECLARE_ALIGNED(32, int32_t, hist2)[64];
} fix;
} u;
int offset;
} DCADSPData;
typedef struct DCACoreDecoder {
AVCodecContext *avctx;
GetBitContext gb;
// Bit stream header
int crc_present; ///< CRC present flag
int npcmblocks; ///< Number of PCM sample blocks
int frame_size; ///< Primary frame byte size
int audio_mode; ///< Audio channel arrangement
int sample_rate; ///< Core audio sampling frequency
int bit_rate; ///< Transmission bit rate
int drc_present; ///< Embedded dynamic range flag
int ts_present; ///< Embedded time stamp flag
int aux_present; ///< Auxiliary data flag
int ext_audio_type; ///< Extension audio descriptor flag
int ext_audio_present; ///< Extended coding flag
int sync_ssf; ///< Audio sync word insertion flag
int lfe_present; ///< Low frequency effects flag
int predictor_history; ///< Predictor history flag switch
int filter_perfect; ///< Multirate interpolator switch
int source_pcm_res; ///< Source PCM resolution
int es_format; ///< Extended surround (ES) mastering flag
int sumdiff_front; ///< Front sum/difference flag
int sumdiff_surround; ///< Surround sum/difference flag
// Primary audio coding header
int nsubframes; ///< Number of subframes
int nchannels; ///< Number of primary audio channels (incl. extension channels)
int ch_mask; ///< Speaker layout mask (incl. LFE and extension channels)
int8_t nsubbands[DCA_CHANNELS]; ///< Subband activity count
int8_t subband_vq_start[DCA_CHANNELS]; ///< High frequency VQ start subband
int8_t joint_intensity_index[DCA_CHANNELS]; ///< Joint intensity coding index
int8_t transition_mode_sel[DCA_CHANNELS]; ///< Transient mode code book
int8_t scale_factor_sel[DCA_CHANNELS]; ///< Scale factor code book
int8_t bit_allocation_sel[DCA_CHANNELS]; ///< Bit allocation quantizer select
int8_t quant_index_sel[DCA_CHANNELS][DCA_CODE_BOOKS]; ///< Quantization index codebook select
int32_t scale_factor_adj[DCA_CHANNELS][DCA_CODE_BOOKS]; ///< Scale factor adjustment
// Primary audio coding side information
int8_t nsubsubframes[DCA_SUBFRAMES]; ///< Subsubframe count for each subframe
int8_t prediction_mode[DCA_CHANNELS][DCA_SUBBANDS_X96]; ///< Prediction mode
int16_t prediction_vq_index[DCA_CHANNELS][DCA_SUBBANDS_X96]; ///< Prediction coefficients VQ address
int8_t bit_allocation[DCA_CHANNELS][DCA_SUBBANDS_X96]; ///< Bit allocation index
int8_t transition_mode[DCA_SUBFRAMES][DCA_CHANNELS][DCA_SUBBANDS]; ///< Transition mode
int32_t scale_factors[DCA_CHANNELS][DCA_SUBBANDS][2]; ///< Scale factors (2x for transients and X96)
int8_t joint_scale_sel[DCA_CHANNELS]; ///< Joint subband codebook select
int32_t joint_scale_factors[DCA_CHANNELS][DCA_SUBBANDS_X96]; ///< Scale factors for joint subband coding
// Auxiliary data
int prim_dmix_embedded; ///< Auxiliary dynamic downmix flag
int prim_dmix_type; ///< Auxiliary primary channel downmix type
int prim_dmix_coeff[DCA_DMIX_CHANNELS_MAX * DCA_CORE_CHANNELS_MAX]; ///< Dynamic downmix code coefficients
// Core extensions
int ext_audio_mask; ///< Bit mask of fully decoded core extensions
// XCH extension data
int xch_pos; ///< Bit position of XCH frame in core substream
// XXCH extension data
int xxch_crc_present; ///< CRC presence flag for XXCH channel set header
int xxch_mask_nbits; ///< Number of bits for loudspeaker mask
int xxch_core_mask; ///< Core loudspeaker activity mask
int xxch_spkr_mask; ///< Loudspeaker layout mask
int xxch_dmix_embedded; ///< Downmix already performed by encoder
int xxch_dmix_scale_inv; ///< Downmix scale factor
int xxch_dmix_mask[DCA_XXCH_CHANNELS_MAX]; ///< Downmix channel mapping mask
int xxch_dmix_coeff[DCA_XXCH_CHANNELS_MAX * DCA_CORE_CHANNELS_MAX]; ///< Downmix coefficients
int xxch_pos; ///< Bit position of XXCH frame in core substream
// X96 extension data
int x96_rev_no; ///< X96 revision number
int x96_crc_present; ///< CRC presence flag for X96 channel set header
int x96_nchannels; ///< Number of primary channels in X96 extension
int x96_high_res; ///< X96 high resolution flag
int x96_subband_start; ///< First encoded subband in X96 extension
int x96_rand; ///< Random seed for generating samples for unallocated X96 subbands
int x96_pos; ///< Bit position of X96 frame in core substream
// Sample buffers
unsigned int x96_subband_size;
int32_t *x96_subband_buffer; ///< X96 subband sample buffer base
int32_t *x96_subband_samples[DCA_CHANNELS][DCA_SUBBANDS_X96]; ///< X96 subband samples
unsigned int subband_size;
int32_t *subband_buffer; ///< Subband sample buffer base
int32_t *subband_samples[DCA_CHANNELS][DCA_SUBBANDS]; ///< Subband samples
int32_t *lfe_samples; ///< Decimated LFE samples
// DSP contexts
DCADSPData dcadsp_data[DCA_CHANNELS]; ///< FIR history buffers
DCADSPContext *dcadsp;
DCADCTContext dcadct;
FFTContext imdct[2];
SynthFilterContext synth;
AVFloatDSPContext *float_dsp;
AVFixedDSPContext *fixed_dsp;
// PCM output data
unsigned int output_size;
void *output_buffer; ///< PCM output buffer base
int32_t *output_samples[DCA_SPEAKER_COUNT]; ///< PCM output for fixed point mode
int32_t output_history_lfe_fixed; ///< LFE PCM history for X96 filter
float output_history_lfe_float; ///< LFE PCM history for X96 filter
int ch_remap[DCA_SPEAKER_COUNT]; ///< Channel to speaker map
int request_mask; ///< Requested channel layout (for stereo downmix)
int npcmsamples; ///< Number of PCM samples per channel
int output_rate; ///< Output sample rate (1x or 2x header rate)
int filter_mode; ///< Previous filtering mode for detecting changes
} DCACoreDecoder;
static inline int ff_dca_core_map_spkr(DCACoreDecoder *core, int spkr)
{
if (core->ch_mask & (1U << spkr))
return spkr;
if (spkr == DCA_SPEAKER_Lss && (core->ch_mask & DCA_SPEAKER_MASK_Ls))
return DCA_SPEAKER_Ls;
if (spkr == DCA_SPEAKER_Rss && (core->ch_mask & DCA_SPEAKER_MASK_Rs))
return DCA_SPEAKER_Rs;
return -1;
}
int ff_dca_core_parse(DCACoreDecoder *s, uint8_t *data, int size);
int ff_dca_core_parse_exss(DCACoreDecoder *s, uint8_t *data, DCAExssAsset *asset);
int ff_dca_core_filter_fixed(DCACoreDecoder *s, int x96_synth);
int ff_dca_core_filter_frame(DCACoreDecoder *s, AVFrame *frame);
av_cold void ff_dca_core_flush(DCACoreDecoder *s);
av_cold int ff_dca_core_init(DCACoreDecoder *s);
av_cold void ff_dca_core_close(DCACoreDecoder *s);
#endif

514
libavcodec/dca_exss.c Normal file
View File

@ -0,0 +1,514 @@
/*
* Copyright (C) 2016 foo86
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "dcadec.h"
#include "dcadata.h"
static int count_chs_for_mask(int mask)
{
return av_popcount(mask) + av_popcount(mask & 0xae66);
}
static void parse_xll_parameters(DCAExssParser *s, DCAExssAsset *asset)
{
// Size of XLL data in extension substream
asset->xll_size = get_bits(&s->gb, s->exss_size_nbits) + 1;
// XLL sync word present flag
if (asset->xll_sync_present = get_bits1(&s->gb)) {
int xll_delay_nbits;
// Peak bit rate smoothing buffer size
skip_bits(&s->gb, 4);
// Number of bits for XLL decoding delay
xll_delay_nbits = get_bits(&s->gb, 5) + 1;
// Initial XLL decoding delay in frames
asset->xll_delay_nframes = get_bits_long(&s->gb, xll_delay_nbits);
// Number of bytes offset to XLL sync
asset->xll_sync_offset = get_bits(&s->gb, s->exss_size_nbits);
} else {
asset->xll_delay_nframes = 0;
asset->xll_sync_offset = 0;
}
}
static void parse_lbr_parameters(DCAExssParser *s, DCAExssAsset *asset)
{
// Size of LBR component in extension substream
asset->lbr_size = get_bits(&s->gb, 14) + 1;
// LBR sync word present flag
if (get_bits1(&s->gb))
// LBR sync distance
skip_bits(&s->gb, 2);
}
static int parse_descriptor(DCAExssParser *s, DCAExssAsset *asset)
{
int i, j, drc_present, descr_size, descr_pos = get_bits_count(&s->gb);
// Size of audio asset descriptor in bytes
descr_size = get_bits(&s->gb, 9) + 1;
// Audio asset identifier
asset->asset_index = get_bits(&s->gb, 3);
//
// Per stream static metadata
//
if (s->static_fields_present) {
// Asset type descriptor presence
if (get_bits1(&s->gb))
// Asset type descriptor
skip_bits(&s->gb, 4);
// Language descriptor presence
if (get_bits1(&s->gb))
// Language descriptor
skip_bits(&s->gb, 24);
// Additional textual information presence
if (get_bits1(&s->gb)) {
// Byte size of additional text info
int text_size = get_bits(&s->gb, 10) + 1;
// Sanity check available size
if (get_bits_left(&s->gb) < text_size * 8)
return AVERROR_INVALIDDATA;
// Additional textual information string
skip_bits_long(&s->gb, text_size * 8);
}
// PCM bit resolution
asset->pcm_bit_res = get_bits(&s->gb, 5) + 1;
// Maximum sample rate
asset->max_sample_rate = ff_dca_sampling_freqs[get_bits(&s->gb, 4)];
// Total number of channels
asset->nchannels_total = get_bits(&s->gb, 8) + 1;
// One to one map channel to speakers
if (asset->one_to_one_map_ch_to_spkr = get_bits1(&s->gb)) {
int spkr_mask_nbits = 0;
int spkr_remap_nsets;
int nspeakers[8];
// Embedded stereo flag
if (asset->nchannels_total > 2)
asset->embedded_stereo = get_bits1(&s->gb);
// Embedded 6 channels flag
if (asset->nchannels_total > 6)
asset->embedded_6ch = get_bits1(&s->gb);
// Speaker mask enabled flag
if (asset->spkr_mask_enabled = get_bits1(&s->gb)) {
// Number of bits for speaker activity mask
spkr_mask_nbits = (get_bits(&s->gb, 2) + 1) << 2;
// Loudspeaker activity mask
asset->spkr_mask = get_bits(&s->gb, spkr_mask_nbits);
}
// Number of speaker remapping sets
if ((spkr_remap_nsets = get_bits(&s->gb, 3)) && !spkr_mask_nbits) {
av_log(s->avctx, AV_LOG_ERROR, "Speaker mask disabled yet there are remapping sets\n");
return AVERROR_INVALIDDATA;
}
// Standard loudspeaker layout mask
for (i = 0; i < spkr_remap_nsets; i++)
nspeakers[i] = count_chs_for_mask(get_bits(&s->gb, spkr_mask_nbits));
for (i = 0; i < spkr_remap_nsets; i++) {
// Number of channels to be decoded for speaker remapping
int nch_for_remaps = get_bits(&s->gb, 5) + 1;
for (j = 0; j < nspeakers[i]; j++) {
// Decoded channels to output speaker mapping mask
int remap_ch_mask = get_bits_long(&s->gb, nch_for_remaps);
// Loudspeaker remapping codes
skip_bits_long(&s->gb, av_popcount(remap_ch_mask) * 5);
}
}
} else {
asset->embedded_stereo = 0;
asset->embedded_6ch = 0;
asset->spkr_mask_enabled = 0;
asset->spkr_mask = 0;
// Representation type
asset->representation_type = get_bits(&s->gb, 3);
}
}
//
// DRC, DNC and mixing metadata
//
// Dynamic range coefficient presence flag
drc_present = get_bits1(&s->gb);
// Code for dynamic range coefficient
if (drc_present)
skip_bits(&s->gb, 8);
// Dialog normalization presence flag
if (get_bits1(&s->gb))
// Dialog normalization code
skip_bits(&s->gb, 5);
// DRC for stereo downmix
if (drc_present && asset->embedded_stereo)
skip_bits(&s->gb, 8);
// Mixing metadata presence flag
if (s->mix_metadata_enabled && get_bits1(&s->gb)) {
int nchannels_dmix;
// External mixing flag
skip_bits1(&s->gb);
// Post mixing / replacement gain adjustment
skip_bits(&s->gb, 6);
// DRC prior to mixing
if (get_bits(&s->gb, 2) == 3)
// Custom code for mixing DRC
skip_bits(&s->gb, 8);
else
// Limit for mixing DRC
skip_bits(&s->gb, 3);
// Scaling type for channels of main audio
// Scaling parameters of main audio
if (get_bits1(&s->gb))
for (i = 0; i < s->nmixoutconfigs; i++)
skip_bits_long(&s->gb, 6 * s->nmixoutchs[i]);
else
skip_bits_long(&s->gb, 6 * s->nmixoutconfigs);
nchannels_dmix = asset->nchannels_total;
if (asset->embedded_6ch)
nchannels_dmix += 6;
if (asset->embedded_stereo)
nchannels_dmix += 2;
for (i = 0; i < s->nmixoutconfigs; i++) {
if (!s->nmixoutchs[i]) {
av_log(s->avctx, AV_LOG_ERROR, "Invalid speaker layout mask for mixing configuration\n");
return AVERROR_INVALIDDATA;
}
for (j = 0; j < nchannels_dmix; j++) {
// Mix output mask
int mix_map_mask = get_bits(&s->gb, s->nmixoutchs[i]);
// Mixing coefficients
skip_bits_long(&s->gb, av_popcount(mix_map_mask) * 6);
}
}
}
//
// Decoder navigation data
//
// Coding mode for the asset
asset->coding_mode = get_bits(&s->gb, 2);
// Coding components used in asset
switch (asset->coding_mode) {
case 0: // Coding mode that may contain multiple coding components
asset->extension_mask = get_bits(&s->gb, 12);
if (asset->extension_mask & DCA_EXSS_CORE) {
// Size of core component in extension substream
asset->core_size = get_bits(&s->gb, 14) + 1;
// Core sync word present flag
if (get_bits1(&s->gb))
// Core sync distance
skip_bits(&s->gb, 2);
}
if (asset->extension_mask & DCA_EXSS_XBR)
// Size of XBR extension in extension substream
asset->xbr_size = get_bits(&s->gb, 14) + 1;
if (asset->extension_mask & DCA_EXSS_XXCH)
// Size of XXCH extension in extension substream
asset->xxch_size = get_bits(&s->gb, 14) + 1;
if (asset->extension_mask & DCA_EXSS_X96)
// Size of X96 extension in extension substream
asset->x96_size = get_bits(&s->gb, 12) + 1;
if (asset->extension_mask & DCA_EXSS_LBR)
parse_lbr_parameters(s, asset);
if (asset->extension_mask & DCA_EXSS_XLL)
parse_xll_parameters(s, asset);
if (asset->extension_mask & DCA_EXSS_RSV1)
skip_bits(&s->gb, 16);
if (asset->extension_mask & DCA_EXSS_RSV2)
skip_bits(&s->gb, 16);
break;
case 1: // Loss-less coding mode without CBR component
asset->extension_mask = DCA_EXSS_XLL;
parse_xll_parameters(s, asset);
break;
case 2: // Low bit rate mode
asset->extension_mask = DCA_EXSS_LBR;
parse_lbr_parameters(s, asset);
break;
case 3: // Auxiliary coding mode
asset->extension_mask = 0;
// Size of auxiliary coded data
skip_bits(&s->gb, 14);
// Auxiliary codec identification
skip_bits(&s->gb, 8);
// Aux sync word present flag
if (get_bits1(&s->gb))
// Aux sync distance
skip_bits(&s->gb, 3);
break;
}
if (asset->extension_mask & DCA_EXSS_XLL)
// DTS-HD stream ID
asset->hd_stream_id = get_bits(&s->gb, 3);
// One to one mixing flag
// Per channel main audio scaling flag
// Main audio scaling codes
// Decode asset in secondary decoder flag
// Revision 2 DRC metadata
// Reserved
// Zero pad
if (ff_dca_seek_bits(&s->gb, descr_pos + descr_size * 8)) {
av_log(s->avctx, AV_LOG_ERROR, "Read past end of EXSS asset descriptor\n");
return AVERROR_INVALIDDATA;
}
return 0;
}
static int set_exss_offsets(DCAExssAsset *asset)
{
int offs = asset->asset_offset;
int size = asset->asset_size;
if (asset->extension_mask & DCA_EXSS_CORE) {
asset->core_offset = offs;
if (asset->core_size > size)
return AVERROR_INVALIDDATA;
offs += asset->core_size;
size -= asset->core_size;
}
if (asset->extension_mask & DCA_EXSS_XBR) {
asset->xbr_offset = offs;
if (asset->xbr_size > size)
return AVERROR_INVALIDDATA;
offs += asset->xbr_size;
size -= asset->xbr_size;
}
if (asset->extension_mask & DCA_EXSS_XXCH) {
asset->xxch_offset = offs;
if (asset->xxch_size > size)
return AVERROR_INVALIDDATA;
offs += asset->xxch_size;
size -= asset->xxch_size;
}
if (asset->extension_mask & DCA_EXSS_X96) {
asset->x96_offset = offs;
if (asset->x96_size > size)
return AVERROR_INVALIDDATA;
offs += asset->x96_size;
size -= asset->x96_size;
}
if (asset->extension_mask & DCA_EXSS_LBR) {
asset->lbr_offset = offs;
if (asset->lbr_size > size)
return AVERROR_INVALIDDATA;
offs += asset->lbr_size;
size -= asset->lbr_size;
}
if (asset->extension_mask & DCA_EXSS_XLL) {
asset->xll_offset = offs;
if (asset->xll_size > size)
return AVERROR_INVALIDDATA;
offs += asset->xll_size;
size -= asset->xll_size;
}
return 0;
}
int ff_dca_exss_parse(DCAExssParser *s, uint8_t *data, int size)
{
int i, ret, offset, wide_hdr, header_size;
if ((ret = init_get_bits8(&s->gb, data, size)) < 0)
return ret;
// Extension substream sync word
skip_bits_long(&s->gb, 32);
// User defined bits
skip_bits(&s->gb, 8);
// Extension substream index
s->exss_index = get_bits(&s->gb, 2);
// Flag indicating short or long header size
wide_hdr = get_bits1(&s->gb);
// Extension substream header length
header_size = get_bits(&s->gb, 8 + 4 * wide_hdr) + 1;
// Check CRC
if ((s->avctx->err_recognition & (AV_EF_CRCCHECK | AV_EF_CAREFUL))
&& ff_dca_check_crc(&s->gb, 32 + 8, header_size * 8)) {
av_log(s->avctx, AV_LOG_ERROR, "Invalid EXSS header checksum\n");
return AVERROR_INVALIDDATA;
}
s->exss_size_nbits = 16 + 4 * wide_hdr;
// Number of bytes of extension substream
s->exss_size = get_bits(&s->gb, s->exss_size_nbits) + 1;
if (s->exss_size > size) {
av_log(s->avctx, AV_LOG_ERROR, "Packet too short for EXSS frame\n");
return AVERROR_INVALIDDATA;
}
// Per stream static fields presence flag
if (s->static_fields_present = get_bits1(&s->gb)) {
int active_exss_mask[8];
// Reference clock code
skip_bits(&s->gb, 2);
// Extension substream frame duration
skip_bits(&s->gb, 3);
// Timecode presence flag
if (get_bits1(&s->gb))
// Timecode data
skip_bits_long(&s->gb, 36);
// Number of defined audio presentations
s->npresents = get_bits(&s->gb, 3) + 1;
if (s->npresents > 1) {
avpriv_request_sample(s->avctx, "%d audio presentations", s->npresents);
return AVERROR_PATCHWELCOME;
}
// Number of audio assets in extension substream
s->nassets = get_bits(&s->gb, 3) + 1;
if (s->nassets > 1) {
avpriv_request_sample(s->avctx, "%d audio assets", s->nassets);
return AVERROR_PATCHWELCOME;
}
// Active extension substream mask for audio presentation
for (i = 0; i < s->npresents; i++)
active_exss_mask[i] = get_bits(&s->gb, s->exss_index + 1);
// Active audio asset mask
for (i = 0; i < s->npresents; i++)
skip_bits_long(&s->gb, av_popcount(active_exss_mask[i]) * 8);
// Mixing metadata enable flag
if (s->mix_metadata_enabled = get_bits1(&s->gb)) {
int spkr_mask_nbits;
// Mixing metadata adjustment level
skip_bits(&s->gb, 2);
// Number of bits for mixer output speaker activity mask
spkr_mask_nbits = (get_bits(&s->gb, 2) + 1) << 2;
// Number of mixing configurations
s->nmixoutconfigs = get_bits(&s->gb, 2) + 1;
// Speaker layout mask for mixer output channels
for (i = 0; i < s->nmixoutconfigs; i++)
s->nmixoutchs[i] = count_chs_for_mask(get_bits(&s->gb, spkr_mask_nbits));
}
} else {
s->npresents = 1;
s->nassets = 1;
}
// Size of encoded asset data in bytes
offset = header_size;
for (i = 0; i < s->nassets; i++) {
s->assets[i].asset_offset = offset;
s->assets[i].asset_size = get_bits(&s->gb, s->exss_size_nbits) + 1;
offset += s->assets[i].asset_size;
if (offset > s->exss_size) {
av_log(s->avctx, AV_LOG_ERROR, "EXSS asset out of bounds\n");
return AVERROR_INVALIDDATA;
}
}
// Audio asset descriptor
for (i = 0; i < s->nassets; i++) {
if ((ret = parse_descriptor(s, &s->assets[i])) < 0)
return ret;
if ((ret = set_exss_offsets(&s->assets[i])) < 0) {
av_log(s->avctx, AV_LOG_ERROR, "Invalid extension size in EXSS asset descriptor\n");
return ret;
}
}
// Backward compatible core present
// Backward compatible core substream index
// Backward compatible core asset index
// Reserved
// Byte align
// CRC16 of extension substream header
if (ff_dca_seek_bits(&s->gb, header_size * 8)) {
av_log(s->avctx, AV_LOG_ERROR, "Read past end of EXSS header\n");
return AVERROR_INVALIDDATA;
}
return 0;
}

92
libavcodec/dca_exss.h Normal file
View File

@ -0,0 +1,92 @@
/*
* Copyright (C) 2016 foo86
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVCODEC_DCA_EXSS_H
#define AVCODEC_DCA_EXSS_H
#include "libavutil/common.h"
#include "avcodec.h"
#include "get_bits.h"
typedef struct DCAExssAsset {
int asset_offset; ///< Offset to asset data from start of substream
int asset_size; ///< Size of encoded asset data
int asset_index; ///< Audio asset identifier
int pcm_bit_res; ///< PCM bit resolution
int max_sample_rate; ///< Maximum sample rate
int nchannels_total; ///< Total number of channels
int one_to_one_map_ch_to_spkr; ///< One to one channel to speaker mapping flag
int embedded_stereo; ///< Embedded stereo flag
int embedded_6ch; ///< Embedded 6 channels flag
int spkr_mask_enabled; ///< Speaker mask enabled flag
int spkr_mask; ///< Loudspeaker activity mask
int representation_type; ///< Representation type
int coding_mode; ///< Coding mode for the asset
int extension_mask; ///< Coding components used in asset
int core_offset; ///< Offset to core component from start of substream
int core_size; ///< Size of core component in extension substream
int xbr_offset; ///< Offset to XBR extension from start of substream
int xbr_size; ///< Size of XBR extension in extension substream
int xxch_offset; ///< Offset to XXCH extension from start of substream
int xxch_size; ///< Size of XXCH extension in extension substream
int x96_offset; ///< Offset to X96 extension from start of substream
int x96_size; ///< Size of X96 extension in extension substream
int lbr_offset; ///< Offset to LBR component from start of substream
int lbr_size; ///< Size of LBR component in extension substream
int xll_offset; ///< Offset to XLL data from start of substream
int xll_size; ///< Size of XLL data in extension substream
int xll_sync_present; ///< XLL sync word present flag
int xll_delay_nframes; ///< Initial XLL decoding delay in frames
int xll_sync_offset; ///< Number of bytes offset to XLL sync
int hd_stream_id; ///< DTS-HD stream ID
} DCAExssAsset;
typedef struct DCAExssParser {
AVCodecContext *avctx;
GetBitContext gb;
int exss_index; ///< Extension substream index
int exss_size_nbits; ///< Number of bits for extension substream size
int exss_size; ///< Number of bytes of extension substream
int static_fields_present; ///< Per stream static fields presence flag
int npresents; ///< Number of defined audio presentations
int nassets; ///< Number of audio assets in extension substream
int mix_metadata_enabled; ///< Mixing metadata enable flag
int nmixoutconfigs; ///< Number of mixing configurations
int nmixoutchs[4]; ///< Speaker layout mask for mixer output channels
DCAExssAsset assets[1]; ///< Audio asset descriptors
} DCAExssParser;
int ff_dca_exss_parse(DCAExssParser *s, uint8_t *data, int size);
#endif

1499
libavcodec/dca_xll.c Normal file

File diff suppressed because it is too large Load Diff

149
libavcodec/dca_xll.h Normal file
View File

@ -0,0 +1,149 @@
/*
* Copyright (C) 2016 foo86
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVCODEC_DCA_XLL_H
#define AVCODEC_DCA_XLL_H
#include "libavutil/common.h"
#include "libavutil/mem.h"
#include "avcodec.h"
#include "internal.h"
#include "get_bits.h"
#include "dca.h"
#include "dcadsp.h"
#include "dca_exss.h"
#define DCA_XLL_CHSETS_MAX 3
#define DCA_XLL_CHANNELS_MAX 8
#define DCA_XLL_BANDS_MAX 2
#define DCA_XLL_ADAPT_PRED_ORDER_MAX 16
#define DCA_XLL_DECI_HISTORY_MAX 8
#define DCA_XLL_DMIX_SCALES_MAX ((DCA_XLL_CHSETS_MAX - 1) * DCA_XLL_CHANNELS_MAX)
#define DCA_XLL_DMIX_COEFFS_MAX (DCA_XLL_DMIX_SCALES_MAX * DCA_XLL_CHANNELS_MAX)
#define DCA_XLL_PBR_BUFFER_MAX (240 << 10)
#define DCA_XLL_SAMPLE_BUFFERS_MAX 3
typedef struct DCAXllBand {
int decor_enabled; ///< Pairwise channel decorrelation flag
int orig_order[DCA_XLL_CHANNELS_MAX]; ///< Original channel order
int decor_coeff[DCA_XLL_CHANNELS_MAX / 2]; ///< Pairwise channel coefficients
int adapt_pred_order[DCA_XLL_CHANNELS_MAX]; ///< Adaptive predictor order
int highest_pred_order; ///< Highest adaptive predictor order
int fixed_pred_order[DCA_XLL_CHANNELS_MAX]; ///< Fixed predictor order
int adapt_refl_coeff[DCA_XLL_CHANNELS_MAX][DCA_XLL_ADAPT_PRED_ORDER_MAX]; ///< Adaptive predictor reflection coefficients
int dmix_embedded; ///< Downmix performed by encoder in frequency band
int lsb_section_size; ///< Size of LSB section in any segment
int nscalablelsbs[DCA_XLL_CHANNELS_MAX]; ///< Number of bits to represent the samples in LSB part
int bit_width_adjust[DCA_XLL_CHANNELS_MAX]; ///< Number of bits discarded by authoring
int32_t *msb_sample_buffer[DCA_XLL_CHANNELS_MAX]; ///< MSB sample buffer pointers
int32_t *lsb_sample_buffer[DCA_XLL_CHANNELS_MAX]; ///< LSB sample buffer pointers or NULL
} DCAXllBand;
typedef struct DCAXllChSet {
// Channel set header
int nchannels; ///< Number of channels in the channel set (N)
int residual_encode; ///< Residual encoding mask (0 - residual, 1 - full channel)
int pcm_bit_res; ///< PCM bit resolution (variable)
int storage_bit_res; ///< Storage bit resolution (16 or 24)
int freq; ///< Original sampling frequency (max. 96000 Hz)
int primary_chset; ///< Primary channel set flag
int dmix_coeffs_present; ///< Downmix coefficients present in stream
int dmix_embedded; ///< Downmix already performed by encoder
int dmix_type; ///< Primary channel set downmix type
int hier_chset; ///< Whether the channel set is part of a hierarchy
int hier_ofs; ///< Number of preceding channels in a hierarchy (M)
int dmix_coeff[DCA_XLL_DMIX_COEFFS_MAX]; ///< Downmixing coefficients
int dmix_scale[DCA_XLL_DMIX_SCALES_MAX]; ///< Downmixing scales
int dmix_scale_inv[DCA_XLL_DMIX_SCALES_MAX]; ///< Inverse downmixing scales
int ch_mask; ///< Channel mask for set
int ch_remap[DCA_XLL_CHANNELS_MAX]; ///< Channel to speaker map
int nfreqbands; ///< Number of frequency bands (1 or 2)
int nabits; ///< Number of bits to read bit allocation coding parameter
DCAXllBand bands[DCA_XLL_BANDS_MAX]; ///< Frequency bands
// Frequency band coding parameters
int seg_common; ///< Segment type
int rice_code_flag[DCA_XLL_CHANNELS_MAX]; ///< Rice coding flag
int bitalloc_hybrid_linear[DCA_XLL_CHANNELS_MAX]; ///< Binary code length for isolated samples
int bitalloc_part_a[DCA_XLL_CHANNELS_MAX]; ///< Coding parameter for part A of segment
int bitalloc_part_b[DCA_XLL_CHANNELS_MAX]; ///< Coding parameter for part B of segment
int nsamples_part_a[DCA_XLL_CHANNELS_MAX]; ///< Number of samples in part A of segment
// Decimator history
DECLARE_ALIGNED(32, int32_t, deci_history)[DCA_XLL_CHANNELS_MAX][DCA_XLL_DECI_HISTORY_MAX]; ///< Decimator history for frequency band 1
// Sample buffers
unsigned int sample_size[DCA_XLL_SAMPLE_BUFFERS_MAX];
int32_t *sample_buffer[DCA_XLL_SAMPLE_BUFFERS_MAX];
} DCAXllChSet;
typedef struct DCAXllDecoder {
AVCodecContext *avctx;
GetBitContext gb;
int frame_size; ///< Number of bytes in a lossless frame
int nchsets; ///< Number of channels sets per frame
int nframesegs; ///< Number of segments per frame
int nsegsamples_log2; ///< log2(nsegsamples)
int nsegsamples; ///< Samples in segment per one frequency band
int nframesamples_log2; ///< log2(nframesamples)
int nframesamples; ///< Samples in frame per one frequency band
int seg_size_nbits; ///< Number of bits used to read segment size
int band_crc_present; ///< Presence of CRC16 within each frequency band
int scalable_lsbs; ///< MSB/LSB split flag
int ch_mask_nbits; ///< Number of bits used to read channel mask
int fixed_lsb_width; ///< Fixed LSB width
DCAXllChSet chset[DCA_XLL_CHSETS_MAX]; ///< Channel sets
int *navi; ///< NAVI table
unsigned int navi_size;
int nfreqbands; ///< Highest number of frequency bands
int nchannels; ///< Total number of channels in a hierarchy
int nreschsets; ///< Number of channel sets that have residual encoded channels
int nactivechsets; ///< Number of active channel sets to decode
int hd_stream_id; ///< Previous DTS-HD stream ID for detecting changes
uint8_t *pbr_buffer; ///< Peak bit rate (PBR) smoothing buffer
int pbr_length; ///< Length in bytes of data currently buffered
int pbr_delay; ///< Delay in frames before decoding buffered data
DCADSPContext *dcadsp;
int output_mask;
int32_t *output_samples[DCA_SPEAKER_COUNT];
} DCAXllDecoder;
int ff_dca_xll_parse(DCAXllDecoder *s, uint8_t *data, DCAExssAsset *asset);
int ff_dca_xll_filter_frame(DCAXllDecoder *s, AVFrame *frame);
av_cold void ff_dca_xll_flush(DCAXllDecoder *s);
av_cold void ff_dca_xll_close(DCAXllDecoder *s);
#endif

417
libavcodec/dcadec.c Normal file
View File

@ -0,0 +1,417 @@
/*
* Copyright (C) 2016 foo86
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "libavutil/opt.h"
#include "libavutil/channel_layout.h"
#include "dcadec.h"
#include "dcamath.h"
#include "dca_syncwords.h"
#include "profiles.h"
#define MIN_PACKET_SIZE 16
#define MAX_PACKET_SIZE 0x104000
int ff_dca_set_channel_layout(AVCodecContext *avctx, int *ch_remap, int dca_mask)
{
static const uint8_t dca2wav_norm[28] = {
2, 0, 1, 9, 10, 3, 8, 4, 5, 9, 10, 6, 7, 12,
13, 14, 3, 6, 7, 11, 12, 14, 16, 15, 17, 8, 4, 5,
};
static const uint8_t dca2wav_wide[28] = {
2, 0, 1, 4, 5, 3, 8, 4, 5, 9, 10, 6, 7, 12,
13, 14, 3, 9, 10, 11, 12, 14, 16, 15, 17, 8, 4, 5,
};
int dca_ch, wav_ch, nchannels = 0;
if (avctx->request_channel_layout & AV_CH_LAYOUT_NATIVE) {
for (dca_ch = 0; dca_ch < DCA_SPEAKER_COUNT; dca_ch++)
if (dca_mask & (1U << dca_ch))
ch_remap[nchannels++] = dca_ch;
avctx->channel_layout = dca_mask;
} else {
int wav_mask = 0;
int wav_map[18];
const uint8_t *dca2wav;
if (dca_mask == DCA_SPEAKER_LAYOUT_7POINT0_WIDE ||
dca_mask == DCA_SPEAKER_LAYOUT_7POINT1_WIDE)
dca2wav = dca2wav_wide;
else
dca2wav = dca2wav_norm;
for (dca_ch = 0; dca_ch < 28; dca_ch++) {
if (dca_mask & (1 << dca_ch)) {
wav_ch = dca2wav[dca_ch];
if (!(wav_mask & (1 << wav_ch))) {
wav_map[wav_ch] = dca_ch;
wav_mask |= 1 << wav_ch;
}
}
}
for (wav_ch = 0; wav_ch < 18; wav_ch++)
if (wav_mask & (1 << wav_ch))
ch_remap[nchannels++] = wav_map[wav_ch];
avctx->channel_layout = wav_mask;
}
avctx->channels = nchannels;
return nchannels;
}
static uint16_t crc16(const uint8_t *data, int size)
{
static const uint16_t crctab[16] = {
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
};
uint16_t res = 0xffff;
int i;
for (i = 0; i < size; i++) {
res = (res << 4) ^ crctab[(data[i] >> 4) ^ (res >> 12)];
res = (res << 4) ^ crctab[(data[i] & 15) ^ (res >> 12)];
}
return res;
}
int ff_dca_check_crc(GetBitContext *s, int p1, int p2)
{
if (((p1 | p2) & 7) || p1 < 0 || p2 > s->size_in_bits || p2 - p1 < 16)
return -1;
if (crc16(s->buffer + p1 / 8, (p2 - p1) / 8))
return -1;
return 0;
}
void ff_dca_downmix_to_stereo_fixed(DCADSPContext *dcadsp, int32_t **samples,
int *coeff_l, int nsamples, int ch_mask)
{
int pos, spkr, max_spkr = av_log2(ch_mask);
int *coeff_r = coeff_l + av_popcount(ch_mask);
av_assert0(DCA_HAS_STEREO(ch_mask));
// Scale left and right channels
pos = (ch_mask & DCA_SPEAKER_MASK_C);
dcadsp->dmix_scale(samples[DCA_SPEAKER_L], coeff_l[pos ], nsamples);
dcadsp->dmix_scale(samples[DCA_SPEAKER_R], coeff_r[pos + 1], nsamples);
// Downmix remaining channels
for (spkr = 0; spkr <= max_spkr; spkr++) {
if (!(ch_mask & (1U << spkr)))
continue;
if (*coeff_l && spkr != DCA_SPEAKER_L)
dcadsp->dmix_add(samples[DCA_SPEAKER_L], samples[spkr],
*coeff_l, nsamples);
if (*coeff_r && spkr != DCA_SPEAKER_R)
dcadsp->dmix_add(samples[DCA_SPEAKER_R], samples[spkr],
*coeff_r, nsamples);
coeff_l++;
coeff_r++;
}
}
void ff_dca_downmix_to_stereo_float(AVFloatDSPContext *fdsp, float **samples,
int *coeff_l, int nsamples, int ch_mask)
{
int pos, spkr, max_spkr = av_log2(ch_mask);
int *coeff_r = coeff_l + av_popcount(ch_mask);
const float scale = 1.0f / (1 << 15);
av_assert0(DCA_HAS_STEREO(ch_mask));
// Scale left and right channels
pos = (ch_mask & DCA_SPEAKER_MASK_C);
fdsp->vector_fmul_scalar(samples[DCA_SPEAKER_L], samples[DCA_SPEAKER_L],
coeff_l[pos ] * scale, nsamples);
fdsp->vector_fmul_scalar(samples[DCA_SPEAKER_R], samples[DCA_SPEAKER_R],
coeff_r[pos + 1] * scale, nsamples);
// Downmix remaining channels
for (spkr = 0; spkr <= max_spkr; spkr++) {
if (!(ch_mask & (1U << spkr)))
continue;
if (*coeff_l && spkr != DCA_SPEAKER_L)
fdsp->vector_fmac_scalar(samples[DCA_SPEAKER_L], samples[spkr],
*coeff_l * scale, nsamples);
if (*coeff_r && spkr != DCA_SPEAKER_R)
fdsp->vector_fmac_scalar(samples[DCA_SPEAKER_R], samples[spkr],
*coeff_r * scale, nsamples);
coeff_l++;
coeff_r++;
}
}
static int convert_bitstream(const uint8_t *src, int src_size, uint8_t *dst, int max_size)
{
switch (AV_RB32(src)) {
case DCA_SYNCWORD_CORE_BE:
case DCA_SYNCWORD_SUBSTREAM:
memcpy(dst, src, src_size);
return src_size;
case DCA_SYNCWORD_CORE_LE:
case DCA_SYNCWORD_CORE_14B_BE:
case DCA_SYNCWORD_CORE_14B_LE:
return avpriv_dca_convert_bitstream(src, src_size, dst, max_size);
default:
return AVERROR_INVALIDDATA;
}
}
static int dcadec_decode_frame(AVCodecContext *avctx, void *data,
int *got_frame_ptr, AVPacket *avpkt)
{
DCAContext *s = avctx->priv_data;
AVFrame *frame = data;
uint8_t *input = avpkt->data;
int input_size = avpkt->size;
int i, ret, prev_packet = s->packet;
if (input_size < MIN_PACKET_SIZE || input_size > MAX_PACKET_SIZE) {
av_log(avctx, AV_LOG_ERROR, "Invalid packet size\n");
return AVERROR_INVALIDDATA;
}
av_fast_malloc(&s->buffer, &s->buffer_size,
FFALIGN(input_size, 4096) + DCA_BUFFER_PADDING_SIZE);
if (!s->buffer)
return AVERROR(ENOMEM);
for (i = 0, ret = AVERROR_INVALIDDATA; i < input_size - MIN_PACKET_SIZE + 1 && ret < 0; i++)
ret = convert_bitstream(input + i, input_size - i, s->buffer, s->buffer_size);
if (ret < 0)
return ret;
input = s->buffer;
input_size = ret;
s->packet = 0;
// Parse backward compatible core sub-stream
if (AV_RB32(input) == DCA_SYNCWORD_CORE_BE) {
int frame_size;
if ((ret = ff_dca_core_parse(&s->core, input, input_size)) < 0) {
s->core_residual_valid = 0;
return ret;
}
s->packet |= DCA_PACKET_CORE;
// EXXS data must be aligned on 4-byte boundary
frame_size = FFALIGN(s->core.frame_size, 4);
if (input_size - 4 > frame_size) {
input += frame_size;
input_size -= frame_size;
}
}
if (!s->core_only) {
DCAExssAsset *asset = NULL;
// Parse extension sub-stream (EXSS)
if (AV_RB32(input) == DCA_SYNCWORD_SUBSTREAM) {
if ((ret = ff_dca_exss_parse(&s->exss, input, input_size)) < 0) {
if (avctx->err_recognition & AV_EF_EXPLODE)
return ret;
} else {
s->packet |= DCA_PACKET_EXSS;
asset = &s->exss.assets[0];
}
}
// Parse XLL component in EXSS
if (asset && (asset->extension_mask & DCA_EXSS_XLL)) {
if ((ret = ff_dca_xll_parse(&s->xll, input, asset)) < 0) {
// Conceal XLL synchronization error
if (ret == AVERROR(EAGAIN)
&& (prev_packet & DCA_PACKET_XLL)
&& (s->packet & DCA_PACKET_CORE))
s->packet |= DCA_PACKET_XLL | DCA_PACKET_RECOVERY;
else if (ret == AVERROR(ENOMEM) || (avctx->err_recognition & AV_EF_EXPLODE))
return ret;
} else {
s->packet |= DCA_PACKET_XLL;
}
}
// Parse core extensions in EXSS or backward compatible core sub-stream
if ((s->packet & DCA_PACKET_CORE)
&& (ret = ff_dca_core_parse_exss(&s->core, input, asset)) < 0)
return ret;
}
// Filter the frame
if (s->packet & DCA_PACKET_XLL) {
if (s->packet & DCA_PACKET_CORE) {
int x96_synth = -1;
// Enable X96 synthesis if needed
if (s->xll.chset[0].freq == 96000 && s->core.sample_rate == 48000)
x96_synth = 1;
if ((ret = ff_dca_core_filter_fixed(&s->core, x96_synth)) < 0) {
s->core_residual_valid = 0;
return ret;
}
// Force lossy downmixed output on the first core frame filtered.
// This prevents audible clicks when seeking and is consistent with
// what reference decoder does when there are multiple channel sets.
if (!s->core_residual_valid) {
if (s->xll.nreschsets > 0 && s->xll.nchsets > 1)
s->packet |= DCA_PACKET_RECOVERY;
s->core_residual_valid = 1;
}
}
if ((ret = ff_dca_xll_filter_frame(&s->xll, frame)) < 0) {
// Fall back to core unless hard error
if (!(s->packet & DCA_PACKET_CORE))
return ret;
if (ret != AVERROR_INVALIDDATA || (avctx->err_recognition & AV_EF_EXPLODE))
return ret;
if ((ret = ff_dca_core_filter_frame(&s->core, frame)) < 0) {
s->core_residual_valid = 0;
return ret;
}
}
} else if (s->packet & DCA_PACKET_CORE) {
if ((ret = ff_dca_core_filter_frame(&s->core, frame)) < 0) {
s->core_residual_valid = 0;
return ret;
}
s->core_residual_valid = !!(s->core.filter_mode & DCA_FILTER_MODE_FIXED);
} else {
return AVERROR_INVALIDDATA;
}
*got_frame_ptr = 1;
return avpkt->size;
}
static av_cold void dcadec_flush(AVCodecContext *avctx)
{
DCAContext *s = avctx->priv_data;
ff_dca_core_flush(&s->core);
ff_dca_xll_flush(&s->xll);
s->core_residual_valid = 0;
}
static av_cold int dcadec_close(AVCodecContext *avctx)
{
DCAContext *s = avctx->priv_data;
ff_dca_core_close(&s->core);
ff_dca_xll_close(&s->xll);
av_freep(&s->buffer);
s->buffer_size = 0;
return 0;
}
static av_cold int dcadec_init(AVCodecContext *avctx)
{
DCAContext *s = avctx->priv_data;
s->avctx = avctx;
s->core.avctx = avctx;
s->exss.avctx = avctx;
s->xll.avctx = avctx;
if (ff_dca_core_init(&s->core) < 0)
return AVERROR(ENOMEM);
ff_dcadsp_init(&s->dcadsp);
s->core.dcadsp = &s->dcadsp;
s->xll.dcadsp = &s->dcadsp;
switch (avctx->request_channel_layout & ~AV_CH_LAYOUT_NATIVE) {
case 0:
s->request_channel_layout = 0;
break;
case AV_CH_LAYOUT_STEREO:
case AV_CH_LAYOUT_STEREO_DOWNMIX:
s->request_channel_layout = DCA_SPEAKER_LAYOUT_STEREO;
break;
case AV_CH_LAYOUT_5POINT0:
s->request_channel_layout = DCA_SPEAKER_LAYOUT_5POINT0;
break;
case AV_CH_LAYOUT_5POINT1:
s->request_channel_layout = DCA_SPEAKER_LAYOUT_5POINT1;
break;
default:
av_log(avctx, AV_LOG_WARNING, "Invalid request_channel_layout\n");
break;
}
avctx->sample_fmt = AV_SAMPLE_FMT_S32P;
avctx->bits_per_raw_sample = 24;
return 0;
}
#define OFFSET(x) offsetof(DCAContext, x)
#define PARAM AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_DECODING_PARAM
static const AVOption dcadec_options[] = {
{ "core_only", "Decode core only without extensions", OFFSET(core_only), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, PARAM },
{ NULL }
};
static const AVClass dcadec_class = {
.class_name = "DCA decoder",
.item_name = av_default_item_name,
.option = dcadec_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 = dcadec_init,
.decode = dcadec_decode_frame,
.close = dcadec_close,
.flush = dcadec_flush,
.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF,
.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_S32P,
AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE },
.priv_class = &dcadec_class,
.profiles = NULL_IF_CONFIG_SMALL(ff_dca_profiles),
.caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
};

80
libavcodec/dcadec.h Normal file
View File

@ -0,0 +1,80 @@
/*
* Copyright (C) 2016 foo86
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVCODEC_DCADEC_H
#define AVCODEC_DCADEC_H
#include "libavutil/common.h"
#include "libavutil/float_dsp.h"
#include "avcodec.h"
#include "get_bits.h"
#include "dca.h"
#include "dcadsp.h"
#include "dca_core.h"
#include "dca_exss.h"
#include "dca_xll.h"
#define DCA_BUFFER_PADDING_SIZE 1024
#define DCA_PACKET_CORE 0x01
#define DCA_PACKET_EXSS 0x02
#define DCA_PACKET_XLL 0x04
#define DCA_PACKET_RECOVERY 0x08
typedef struct DCAContext {
const AVClass *class; ///< class for AVOptions
AVCodecContext *avctx;
DCACoreDecoder core; ///< Core decoder context
DCAExssParser exss; ///< EXSS parser context
DCAXllDecoder xll; ///< XLL decoder context
DCADSPContext dcadsp;
uint8_t *buffer; ///< Packet buffer
unsigned int buffer_size;
int packet; ///< Packet flags
int core_residual_valid; ///< Core valid for residual decoding
int request_channel_layout; ///< Converted from avctx.request_channel_layout
int core_only; ///< Core only decoding flag
} DCAContext;
int ff_dca_set_channel_layout(AVCodecContext *avctx, int *ch_remap, int dca_mask);
int ff_dca_check_crc(GetBitContext *s, int p1, int p2);
void ff_dca_downmix_to_stereo_fixed(DCADSPContext *dcadsp, int32_t **samples,
int *coeff_l, int nsamples, int ch_mask);
void ff_dca_downmix_to_stereo_float(AVFloatDSPContext *fdsp, float **samples,
int *coeff_l, int nsamples, int ch_mask);
static inline int ff_dca_seek_bits(GetBitContext *s, int p)
{
if (p < s->index || p > s->size_in_bits)
return -1;
s->index = p;
return 0;
}
#endif

413
libavcodec/dcadsp.c Normal file
View File

@ -0,0 +1,413 @@
/*
* Copyright (C) 2016 foo86
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "libavutil/mem.h"
#include "dcadsp.h"
#include "dcamath.h"
static void decode_hf_c(int32_t **dst,
const int32_t *vq_index,
const int8_t hf_vq[1024][32],
int32_t scale_factors[32][2],
intptr_t sb_start, intptr_t sb_end,
intptr_t ofs, intptr_t len)
{
int i, j;
for (i = sb_start; i < sb_end; i++) {
const int8_t *coeff = hf_vq[vq_index[i]];
int32_t scale = scale_factors[i][0];
for (j = 0; j < len; j++)
dst[i][j + ofs] = clip23(coeff[j] * scale + (1 << 3) >> 4);
}
}
static void decode_joint_c(int32_t **dst, int32_t **src,
const int32_t *scale_factors,
intptr_t sb_start, intptr_t sb_end,
intptr_t ofs, intptr_t len)
{
int i, j;
for (i = sb_start; i < sb_end; i++) {
int32_t scale = scale_factors[i];
for (j = 0; j < len; j++)
dst[i][j + ofs] = clip23(mul17(src[i][j + ofs], scale));
}
}
static void lfe_fir_float_c(float *pcm_samples, int32_t *lfe_samples,
const float *filter_coeff, intptr_t npcmblocks,
int dec_select)
{
// Select decimation factor
int factor = 64 << dec_select;
int ncoeffs = 8 >> dec_select;
int nlfesamples = npcmblocks >> (dec_select + 1);
int i, j, k;
for (i = 0; i < nlfesamples; i++) {
// One decimated sample generates 64 or 128 interpolated ones
for (j = 0; j < factor / 2; j++) {
float a = 0;
float b = 0;
for (k = 0; k < ncoeffs; k++) {
a += filter_coeff[ j * ncoeffs + k] * lfe_samples[-k];
b += filter_coeff[255 - j * ncoeffs - k] * lfe_samples[-k];
}
pcm_samples[ j] = a;
pcm_samples[factor / 2 + j] = b;
}
lfe_samples++;
pcm_samples += factor;
}
}
static void lfe_fir1_float_c(float *pcm_samples, int32_t *lfe_samples,
const float *filter_coeff, intptr_t npcmblocks)
{
lfe_fir_float_c(pcm_samples, lfe_samples, filter_coeff, npcmblocks, 0);
}
static void lfe_fir2_float_c(float *pcm_samples, int32_t *lfe_samples,
const float *filter_coeff, intptr_t npcmblocks)
{
lfe_fir_float_c(pcm_samples, lfe_samples, filter_coeff, npcmblocks, 1);
}
static void lfe_x96_float_c(float *dst, const float *src,
float *hist, intptr_t len)
{
float prev = *hist;
int i;
for (i = 0; i < len; i++) {
float a = 0.25f * src[i] + 0.75f * prev;
float b = 0.75f * src[i] + 0.25f * prev;
prev = src[i];
*dst++ = a;
*dst++ = b;
}
*hist = prev;
}
static void sub_qmf32_float_c(SynthFilterContext *synth,
FFTContext *imdct,
float *pcm_samples,
int32_t **subband_samples_lo,
int32_t **subband_samples_hi,
float *hist1, int *offset, float *hist2,
const float *filter_coeff, intptr_t npcmblocks,
float scale)
{
LOCAL_ALIGNED(32, float, input, [32]);
int i, j;
for (j = 0; j < npcmblocks; j++) {
// Load in one sample from each subband
for (i = 0; i < 32; i++) {
if ((i - 1) & 2)
input[i] = -subband_samples_lo[i][j];
else
input[i] = subband_samples_lo[i][j];
}
// One subband sample generates 32 interpolated ones
synth->synth_filter_float(imdct, hist1, offset,
hist2, filter_coeff,
pcm_samples, input, scale);
pcm_samples += 32;
}
}
static void sub_qmf64_float_c(SynthFilterContext *synth,
FFTContext *imdct,
float *pcm_samples,
int32_t **subband_samples_lo,
int32_t **subband_samples_hi,
float *hist1, int *offset, float *hist2,
const float *filter_coeff, intptr_t npcmblocks,
float scale)
{
LOCAL_ALIGNED(32, float, input, [64]);
int i, j;
if (!subband_samples_hi)
memset(&input[32], 0, sizeof(input[0]) * 32);
for (j = 0; j < npcmblocks; j++) {
// Load in one sample from each subband
if (subband_samples_hi) {
// Full 64 subbands, first 32 are residual coded
for (i = 0; i < 32; i++) {
if ((i - 1) & 2)
input[i] = -subband_samples_lo[i][j] - subband_samples_hi[i][j];
else
input[i] = subband_samples_lo[i][j] + subband_samples_hi[i][j];
}
for (i = 32; i < 64; i++) {
if ((i - 1) & 2)
input[i] = -subband_samples_hi[i][j];
else
input[i] = subband_samples_hi[i][j];
}
} else {
// Only first 32 subbands
for (i = 0; i < 32; i++) {
if ((i - 1) & 2)
input[i] = -subband_samples_lo[i][j];
else
input[i] = subband_samples_lo[i][j];
}
}
// One subband sample generates 64 interpolated ones
synth->synth_filter_float_64(imdct, hist1, offset,
hist2, filter_coeff,
pcm_samples, input, scale);
pcm_samples += 64;
}
}
static void lfe_fir_fixed_c(int32_t *pcm_samples, int32_t *lfe_samples,
const int32_t *filter_coeff, intptr_t npcmblocks)
{
// Select decimation factor
int nlfesamples = npcmblocks >> 1;
int i, j, k;
for (i = 0; i < nlfesamples; i++) {
// One decimated sample generates 64 interpolated ones
for (j = 0; j < 32; j++) {
int64_t a = 0;
int64_t b = 0;
for (k = 0; k < 8; k++) {
a += (int64_t)filter_coeff[ j * 8 + k] * lfe_samples[-k];
b += (int64_t)filter_coeff[255 - j * 8 - k] * lfe_samples[-k];
}
pcm_samples[ j] = clip23(norm23(a));
pcm_samples[32 + j] = clip23(norm23(b));
}
lfe_samples++;
pcm_samples += 64;
}
}
static void lfe_x96_fixed_c(int32_t *dst, const int32_t *src,
int32_t *hist, intptr_t len)
{
int32_t prev = *hist;
int i;
for (i = 0; i < len; i++) {
int64_t a = INT64_C(2097471) * src[i] + INT64_C(6291137) * prev;
int64_t b = INT64_C(6291137) * src[i] + INT64_C(2097471) * prev;
prev = src[i];
*dst++ = clip23(norm23(a));
*dst++ = clip23(norm23(b));
}
*hist = prev;
}
static void sub_qmf32_fixed_c(SynthFilterContext *synth,
DCADCTContext *imdct,
int32_t *pcm_samples,
int32_t **subband_samples_lo,
int32_t **subband_samples_hi,
int32_t *hist1, int *offset, int32_t *hist2,
const int32_t *filter_coeff, intptr_t npcmblocks)
{
LOCAL_ALIGNED(32, int32_t, input, [32]);
int i, j;
for (j = 0; j < npcmblocks; j++) {
// Load in one sample from each subband
for (i = 0; i < 32; i++)
input[i] = subband_samples_lo[i][j];
// One subband sample generates 32 interpolated ones
synth->synth_filter_fixed(imdct, hist1, offset,
hist2, filter_coeff,
pcm_samples, input);
pcm_samples += 32;
}
}
static void sub_qmf64_fixed_c(SynthFilterContext *synth,
DCADCTContext *imdct,
int32_t *pcm_samples,
int32_t **subband_samples_lo,
int32_t **subband_samples_hi,
int32_t *hist1, int *offset, int32_t *hist2,
const int32_t *filter_coeff, intptr_t npcmblocks)
{
LOCAL_ALIGNED(32, int32_t, input, [64]);
int i, j;
if (!subband_samples_hi)
memset(&input[32], 0, sizeof(input[0]) * 32);
for (j = 0; j < npcmblocks; j++) {
// Load in one sample from each subband
if (subband_samples_hi) {
// Full 64 subbands, first 32 are residual coded
for (i = 0; i < 32; i++)
input[i] = subband_samples_lo[i][j] + subband_samples_hi[i][j];
for (i = 32; i < 64; i++)
input[i] = subband_samples_hi[i][j];
} else {
// Only first 32 subbands
for (i = 0; i < 32; i++)
input[i] = subband_samples_lo[i][j];
}
// One subband sample generates 64 interpolated ones
synth->synth_filter_fixed_64(imdct, hist1, offset,
hist2, filter_coeff,
pcm_samples, input);
pcm_samples += 64;
}
}
static void decor_c(int32_t *dst, const int32_t *src, intptr_t coeff, intptr_t len)
{
int i;
for (i = 0; i < len; i++)
dst[i] += src[i] * coeff + (1 << 2) >> 3;
}
static void dmix_sub_xch_c(int32_t *dst1, int32_t *dst2,
const int32_t *src, intptr_t len)
{
int i;
for (i = 0; i < len; i++) {
int32_t cs = mul23(src[i], 5931520 /* M_SQRT1_2 * (1 << 23) */);
dst1[i] -= cs;
dst2[i] -= cs;
}
}
static void dmix_sub_c(int32_t *dst, const int32_t *src, intptr_t coeff, intptr_t len)
{
int i;
for (i = 0; i < len; i++)
dst[i] -= mul15(src[i], coeff);
}
static void dmix_add_c(int32_t *dst, const int32_t *src, intptr_t coeff, intptr_t len)
{
int i;
for (i = 0; i < len; i++)
dst[i] += mul15(src[i], coeff);
}
static void dmix_scale_c(int32_t *dst, intptr_t scale, intptr_t len)
{
int i;
for (i = 0; i < len; i++)
dst[i] = mul15(dst[i], scale);
}
static void dmix_scale_inv_c(int32_t *dst, intptr_t scale_inv, intptr_t len)
{
int i;
for (i = 0; i < len; i++)
dst[i] = mul16(dst[i], scale_inv);
}
static void filter0(int32_t *dst, const int32_t *src, int32_t coeff, intptr_t len)
{
int i;
for (i = 0; i < len; i++)
dst[i] -= mul22(src[i], coeff);
}
static void filter1(int32_t *dst, const int32_t *src, int32_t coeff, intptr_t len)
{
int i;
for (i = 0; i < len; i++)
dst[i] -= mul23(src[i], coeff);
}
static void assemble_freq_bands_c(int32_t *dst, int32_t *src0, int32_t *src1,
const int32_t *coeff, intptr_t len)
{
int i;
filter0(src0, src1, coeff[0], len);
filter0(src1, src0, coeff[1], len);
filter0(src0, src1, coeff[2], len);
filter0(src1, src0, coeff[3], len);
for (i = 0; i < 8; i++, src0--) {
filter1(src0, src1, coeff[i + 4], len);
filter1(src1, src0, coeff[i + 12], len);
filter1(src0, src1, coeff[i + 4], len);
}
for (i = 0; i < len; i++) {
*dst++ = *src1++;
*dst++ = *++src0;
}
}
av_cold void ff_dcadsp_init(DCADSPContext *s)
{
s->decode_hf = decode_hf_c;
s->decode_joint = decode_joint_c;
s->lfe_fir_float[0] = lfe_fir1_float_c;
s->lfe_fir_float[1] = lfe_fir2_float_c;
s->lfe_x96_float = lfe_x96_float_c;
s->sub_qmf_float[0] = sub_qmf32_float_c;
s->sub_qmf_float[1] = sub_qmf64_float_c;
s->lfe_fir_fixed = lfe_fir_fixed_c;
s->lfe_x96_fixed = lfe_x96_fixed_c;
s->sub_qmf_fixed[0] = sub_qmf32_fixed_c;
s->sub_qmf_fixed[1] = sub_qmf64_fixed_c;
s->decor = decor_c;
s->dmix_sub_xch = dmix_sub_xch_c;
s->dmix_sub = dmix_sub_c;
s->dmix_add = dmix_add_c;
s->dmix_scale = dmix_scale_c;
s->dmix_scale_inv = dmix_scale_inv_c;
s->assemble_freq_bands = assemble_freq_bands_c;
}

91
libavcodec/dcadsp.h Normal file
View File

@ -0,0 +1,91 @@
/*
* Copyright (C) 2016 foo86
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVCODEC_DCADSP_H
#define AVCODEC_DCADSP_H
#include "libavutil/common.h"
#include "fft.h"
#include "dcadct.h"
#include "synth_filter.h"
typedef struct DCADSPContext {
void (*decode_hf)(int32_t **dst,
const int32_t *vq_index,
const int8_t hf_vq[1024][32],
int32_t scale_factors[32][2],
intptr_t sb_start, intptr_t sb_end,
intptr_t ofs, intptr_t len);
void (*decode_joint)(int32_t **dst, int32_t **src,
const int32_t *scale_factors,
intptr_t sb_start, intptr_t sb_end,
intptr_t ofs, intptr_t len);
void (*lfe_fir_float[2])(float *pcm_samples, int32_t *lfe_samples,
const float *filter_coeff, intptr_t npcmblocks);
void (*lfe_x96_float)(float *dst, const float *src,
float *hist, intptr_t len);
void (*sub_qmf_float[2])(SynthFilterContext *synth,
FFTContext *imdct,
float *pcm_samples,
int32_t **subband_samples_lo,
int32_t **subband_samples_hi,
float *hist1, int *offset, float *hist2,
const float *filter_coeff, intptr_t npcmblocks,
float scale);
void (*lfe_fir_fixed)(int32_t *pcm_samples, int32_t *lfe_samples,
const int32_t *filter_coeff, intptr_t npcmblocks);
void (*lfe_x96_fixed)(int32_t *dst, const int32_t *src,
int32_t *hist, intptr_t len);
void (*sub_qmf_fixed[2])(SynthFilterContext *synth,
DCADCTContext *imdct,
int32_t *pcm_samples,
int32_t **subband_samples_lo,
int32_t **subband_samples_hi,
int32_t *hist1, int *offset, int32_t *hist2,
const int32_t *filter_coeff, intptr_t npcmblocks);
void (*decor)(int32_t *dst, const int32_t *src, intptr_t coeff, intptr_t len);
void (*dmix_sub_xch)(int32_t *dst1, int32_t *dst2,
const int32_t *src, intptr_t len);
void (*dmix_sub)(int32_t *dst, const int32_t *src, intptr_t coeff, intptr_t len);
void (*dmix_add)(int32_t *dst, const int32_t *src, intptr_t coeff, intptr_t len);
void (*dmix_scale)(int32_t *dst, intptr_t scale, intptr_t len);
void (*dmix_scale_inv)(int32_t *dst, intptr_t scale_inv, intptr_t len);
void (*assemble_freq_bands)(int32_t *dst, int32_t *src0, int32_t *src1,
const int32_t *coeff, intptr_t len);
} DCADSPContext;
av_cold void ff_dcadsp_init(DCADSPContext *s);
#endif

View File

@ -30,7 +30,7 @@
#define LIBAVCODEC_VERSION_MAJOR 57
#define LIBAVCODEC_VERSION_MINOR 24
#define LIBAVCODEC_VERSION_MICRO 100
#define LIBAVCODEC_VERSION_MICRO 101
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
LIBAVCODEC_VERSION_MINOR, \

View File

@ -44,7 +44,7 @@ OBJS-$(CONFIG_ADPCM_G722_ENCODER) += x86/g722dsp_init.o
OBJS-$(CONFIG_ALAC_DECODER) += x86/alacdsp_init.o
OBJS-$(CONFIG_APNG_DECODER) += x86/pngdsp_init.o
OBJS-$(CONFIG_CAVS_DECODER) += x86/cavsdsp.o
#OBJS-$(CONFIG_DCA_DECODER) += x86/synth_filter_init.o
OBJS-$(CONFIG_DCA_DECODER) += x86/synth_filter_init.o
OBJS-$(CONFIG_DNXHD_ENCODER) += x86/dnxhdenc_init.o
OBJS-$(CONFIG_HEVC_DECODER) += x86/hevcdsp_init.o
OBJS-$(CONFIG_JPEG2000_DECODER) += x86/jpeg2000dsp_init.o
@ -132,7 +132,7 @@ YASM-OBJS-$(CONFIG_ADPCM_G722_DECODER) += x86/g722dsp.o
YASM-OBJS-$(CONFIG_ADPCM_G722_ENCODER) += x86/g722dsp.o
YASM-OBJS-$(CONFIG_ALAC_DECODER) += x86/alacdsp.o
YASM-OBJS-$(CONFIG_APNG_DECODER) += x86/pngdsp.o
#YASM-OBJS-$(CONFIG_DCA_DECODER) += x86/synth_filter.o
YASM-OBJS-$(CONFIG_DCA_DECODER) += x86/synth_filter.o
YASM-OBJS-$(CONFIG_DIRAC_DECODER) += x86/diracdsp_mmx.o x86/diracdsp_yasm.o \
x86/dwt_yasm.o
YASM-OBJS-$(CONFIG_DNXHD_ENCODER) += x86/dnxhdenc.o

View File

@ -1,7 +1,7 @@
# libavcodec tests
AVCODECOBJS-$(CONFIG_ALAC_DECODER) += alacdsp.o
AVCODECOBJS-$(CONFIG_BSWAPDSP) += bswapdsp.o
#AVCODECOBJS-$(CONFIG_DCA_DECODER) += synth_filter.o
AVCODECOBJS-$(CONFIG_DCA_DECODER) += synth_filter.o
AVCODECOBJS-$(CONFIG_FLACDSP) += flacdsp.o
AVCODECOBJS-$(CONFIG_FMTCONVERT) += fmtconvert.o
AVCODECOBJS-$(CONFIG_H264PRED) += h264pred.o

View File

@ -71,9 +71,9 @@ static const struct {
#if CONFIG_BSWAPDSP
{ "bswapdsp", checkasm_check_bswapdsp },
#endif
/* #if CONFIG_DCA_DECODER
#if CONFIG_DCA_DECODER
{ "synth_filter", checkasm_check_synth_filter },
#endif*/
#endif
#if CONFIG_FLACDSP
{ "flacdsp", checkasm_check_flacdsp },
#endif

View File

@ -99,14 +99,14 @@ FATE_ACODEC-$(call ENCDEC, ALAC, MOV) += fate-acodec-alac
fate-acodec-alac: FMT = mov
fate-acodec-alac: CODEC = alac -compression_level 1
#FATE_ACODEC-$(call ENCDEC, DCA, DTS) += fate-acodec-dca
FATE_ACODEC-$(call ENCDEC, DCA, DTS) += fate-acodec-dca
fate-acodec-dca: tests/data/asynth-44100-2.wav
fate-acodec-dca: SRC = tests/data/asynth-44100-2.wav
fate-acodec-dca: CMD = md5 -i $(TARGET_PATH)/$(SRC) -c:a dca -strict -2 -f dts -flags +bitexact
fate-acodec-dca: CMP = oneline
fate-acodec-dca: REF = 7ffdefdf47069289990755c79387cc90
#FATE_ACODEC-$(call ENCDEC, DCA, WAV) += fate-acodec-dca2
FATE_ACODEC-$(call ENCDEC, DCA, WAV) += fate-acodec-dca2
fate-acodec-dca2: CMD = enc_dec_pcm dts wav s16le $(SRC) -c:a dca -strict -2 -flags +bitexact
fate-acodec-dca2: REF = $(SRC)
fate-acodec-dca2: CMP = stddev

View File

@ -21,7 +21,7 @@ fate-dca-core: CMD = pcm -i $(TARGET_SAMPLES)/dts/dts.ts
fate-dca-core: CMP = oneoff
fate-dca-core: REF = $(SAMPLES)/dts/dts.pcm
#FATE_SAMPLES_AUDIO-$(CONFIG_DCA_DECODER) += $(FATE_DCA-yes)
FATE_SAMPLES_AUDIO-$(CONFIG_DCA_DECODER) += $(FATE_DCA-yes)
fate-dca: $(FATE_DCA-yes)
FATE_SAMPLES_AUDIO-$(call DEMDEC, DSICIN, DSICINAUDIO) += fate-delphine-cin-audio
@ -31,7 +31,7 @@ FATE_SAMPLES_AUDIO-$(call DEMDEC, DSS, DSS_SP) += fate-dss-lp fate-dss-sp
fate-dss-lp: CMD = framecrc -i $(TARGET_SAMPLES)/dss/lp.dss -frames 30
fate-dss-sp: CMD = framecrc -i $(TARGET_SAMPLES)/dss/sp.dss -frames 30
#FATE_SAMPLES_AUDIO-$(call DEMDEC, DTS, DCA) += fate-dts_es
FATE_SAMPLES_AUDIO-$(call DEMDEC, DTS, DCA) += fate-dts_es
fate-dts_es: CMD = pcm -i $(TARGET_SAMPLES)/dts/dts_es.dts
fate-dts_es: CMP = oneoff
fate-dts_es: REF = $(SAMPLES)/dts/dts_es_2.pcm