mirror of https://github.com/FFmpeg/FFmpeg.git
parent
0930b2dd1f
commit
ae5b2c5250
22 changed files with 6085 additions and 16 deletions
File diff suppressed because it is too large
Load Diff
@ -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 |
@ -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; |
||||
} |
@ -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 |
File diff suppressed because it is too large
Load Diff
@ -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 |
@ -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, |
||||
}; |
@ -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 |
@ -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; |
||||
} |
@ -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 |
Loading…
Reference in new issue