Commit 46089967 authored by foo86's avatar foo86 Committed by Hendrik Leppkes

avcodec/dca: remove old decoder

Remove all files and functions which are not going to be reused,
and disable all functions and FATE tests temporarily which will be.
parent b552f3af
......@@ -2271,7 +2271,6 @@ comfortnoise_encoder_select="lpc"
cook_decoder_select="audiodsp mdct sinewin"
cscd_decoder_select="lzo"
cscd_decoder_suggest="zlib"
dca_decoder_select="fmtconvert mdct"
dds_decoder_select="texturedsp"
dirac_decoder_select="dirac_parse dwt golomb videodsp mpegvideoenc"
dnxhd_decoder_select="blockdsp idctdsp"
......
......@@ -222,9 +222,6 @@ 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 dcadsp.o \
dcadata.o dca_exss.o \
dca_xll.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 \
......
OBJS-$(CONFIG_DCA_DECODER) += aarch64/dcadsp_init.o \
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
......@@ -18,8 +17,7 @@ OBJS-$(CONFIG_VORBIS_DECODER) += aarch64/vorbisdsp_init.o
ARMV8-OBJS-$(CONFIG_VIDEODSP) += aarch64/videodsp.o
NEON-OBJS-$(CONFIG_DCA_DECODER) += aarch64/dcadsp_neon.o \
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
......
/*
* Copyright (c) 2010 Mans Rullgard <mans@mansr.com>
*
* 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 "config.h"
#include "libavutil/aarch64/cpu.h"
#include "libavutil/attributes.h"
#include "libavutil/internal.h"
#include "libavcodec/dcadsp.h"
void ff_dca_lfe_fir0_neon(float *out, const float *in, const float *coefs);
void ff_dca_lfe_fir1_neon(float *out, const float *in, const float *coefs);
av_cold void ff_dcadsp_init_aarch64(DCADSPContext *s)
{
int cpu_flags = av_get_cpu_flags();
if (have_neon(cpu_flags)) {
s->lfe_fir[0] = ff_dca_lfe_fir0_neon;
s->lfe_fir[1] = ff_dca_lfe_fir1_neon;
}
}
/*
* Copyright (c) 2010 Mans Rullgard <mans@mansr.com>
* Copyright (c) 2015 Janne Grunau <janne-libav@jannau.net>
*
* 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/aarch64/asm.S"
function ff_dca_lfe_fir0_neon, export=1
mov x3, #32 // decifactor
sub x1, x1, #7*4
add x4, x0, #2*32*4 - 16 // out2
mov x7, #-16
ld1 {v0.4s,v1.4s}, [x1]
// reverse [-num_coeffs + 1, 0]
ext v3.16b, v0.16b, v0.16b, #8
ext v2.16b, v1.16b, v1.16b, #8
rev64 v3.4s, v3.4s
rev64 v2.4s, v2.4s
1:
ld1 {v4.4s,v5.4s}, [x2], #32
ld1 {v6.4s,v7.4s}, [x2], #32
subs x3, x3, #4
fmul v16.4s, v2.4s, v4.4s
fmul v23.4s, v0.4s, v4.4s
fmul v17.4s, v2.4s, v6.4s
fmul v22.4s, v0.4s, v6.4s
fmla v16.4s, v3.4s, v5.4s
fmla v23.4s, v1.4s, v5.4s
ld1 {v4.4s,v5.4s}, [x2], #32
fmla v17.4s, v3.4s, v7.4s
fmla v22.4s, v1.4s, v7.4s
ld1 {v6.4s,v7.4s}, [x2], #32
fmul v18.4s, v2.4s, v4.4s
fmul v21.4s, v0.4s, v4.4s
fmul v19.4s, v2.4s, v6.4s
fmul v20.4s, v0.4s, v6.4s
fmla v18.4s, v3.4s, v5.4s
fmla v21.4s, v1.4s, v5.4s
fmla v19.4s, v3.4s, v7.4s
fmla v20.4s, v1.4s, v7.4s
faddp v16.4s, v16.4s, v17.4s
faddp v18.4s, v18.4s, v19.4s
faddp v20.4s, v20.4s, v21.4s
faddp v22.4s, v22.4s, v23.4s
faddp v16.4s, v16.4s, v18.4s
faddp v20.4s, v20.4s, v22.4s
st1 {v16.4s}, [x0], #16
st1 {v20.4s}, [x4], x7
b.gt 1b
ret
endfunc
function ff_dca_lfe_fir1_neon, export=1
mov x3, #64 // decifactor
sub x1, x1, #3*4
add x4, x0, #2*64*4 - 16 // out2
mov x7, #-16
ld1 {v0.4s}, [x1]
// reverse [-num_coeffs + 1, 0]
ext v1.16b, v0.16b, v0.16b, #8
rev64 v1.4s, v1.4s
1:
ld1 {v4.4s,v5.4s}, [x2], #32
ld1 {v6.4s,v7.4s}, [x2], #32
subs x3, x3, #4
fmul v16.4s, v1.4s, v4.4s
fmul v23.4s, v0.4s, v4.4s
fmul v17.4s, v1.4s, v5.4s
fmul v22.4s, v0.4s, v5.4s
fmul v18.4s, v1.4s, v6.4s
fmul v21.4s, v0.4s, v6.4s
fmul v19.4s, v1.4s, v7.4s
fmul v20.4s, v0.4s, v7.4s
faddp v16.4s, v16.4s, v17.4s
faddp v18.4s, v18.4s, v19.4s
faddp v20.4s, v20.4s, v21.4s
faddp v22.4s, v22.4s, v23.4s
faddp v16.4s, v16.4s, v18.4s
faddp v20.4s, v20.4s, v22.4s
st1 {v16.4s}, [x0], #16
st1 {v20.4s}, [x4], x7
b.gt 1b
ret
endfunc
......@@ -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_ENCDEC (DCA, dca);
REGISTER_ENCODER(DCA, dca);
REGISTER_DECODER(DSD_LSBF, dsd_lsbf);
REGISTER_DECODER(DSD_MSBF, dsd_msbf);
REGISTER_DECODER(DSD_LSBF_PLANAR, dsd_lsbf_planar);
......
......@@ -36,8 +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/dcadsp_init_arm.o \
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
......@@ -88,8 +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/dcadsp_vfp.o \
arm/synth_filter_vfp.o
#VFP-OBJS-$(CONFIG_DCA_DECODER) += arm/synth_filter_vfp.o
# NEON optimizations
......@@ -128,8 +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/dcadsp_neon.o \
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 \
......
......@@ -24,7 +24,6 @@
#include <stdint.h>
#include "config.h"
#include "libavcodec/dcadsp.h"
#include "libavcodec/mathops.h"
#if HAVE_ARMV6_INLINE && AV_GCC_VERSION_AT_LEAST(4,4) && !CONFIG_THUMB
......
/*
* Copyright (c) 2010 Mans Rullgard <mans@mansr.com>
*
* 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 "config.h"
#include "libavutil/arm/cpu.h"
#include "libavutil/attributes.h"
#include "libavcodec/dcadsp.h"
void ff_dca_lfe_fir0_neon(float *out, const float *in, const float *coefs);
void ff_dca_lfe_fir1_neon(float *out, const float *in, const float *coefs);
void ff_dca_lfe_fir32_vfp(float *out, const float *in, const float *coefs);
void ff_dca_lfe_fir64_vfp(float *out, const float *in, const float *coefs);
void ff_dca_qmf_32_subbands_vfp(float samples_in[32][8], int sb_act,
SynthFilterContext *synth, FFTContext *imdct,
float synth_buf_ptr[512],
int *synth_buf_offset, float synth_buf2[32],
const float window[512], float *samples_out,
float raXin[32], float scale);
av_cold void ff_dcadsp_init_arm(DCADSPContext *s)
{
int cpu_flags = av_get_cpu_flags();
if (have_vfp_vm(cpu_flags)) {
s->lfe_fir[0] = ff_dca_lfe_fir32_vfp;
s->lfe_fir[1] = ff_dca_lfe_fir64_vfp;
s->qmf_32_subbands = ff_dca_qmf_32_subbands_vfp;
}
if (have_neon(cpu_flags)) {
s->lfe_fir[0] = ff_dca_lfe_fir0_neon;
s->lfe_fir[1] = ff_dca_lfe_fir1_neon;
}
}
/*
* Copyright (c) 2010 Mans Rullgard <mans@mansr.com>
*
* 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/arm/asm.S"
function ff_dca_lfe_fir0_neon, export=1
push {r4-r6,lr}
mov r3, #32 @ decifactor
mov r6, #256/32
b dca_lfe_fir
endfunc
function ff_dca_lfe_fir1_neon, export=1
push {r4-r6,lr}
mov r3, #64 @ decifactor
mov r6, #256/64
dca_lfe_fir:
add r4, r0, r3, lsl #2 @ out2
add r5, r2, #256*4-16 @ cf1
sub r1, r1, #12
mov lr, #-16
1:
vmov.f32 q2, #0.0 @ v0
vmov.f32 q3, #0.0 @ v1
mov r12, r6
2:
vld1.32 {q8}, [r2,:128]! @ cf0
vld1.32 {q9}, [r5,:128], lr @ cf1
vld1.32 {q1}, [r1], lr @ in
subs r12, r12, #4
vrev64.32 q10, q8
vmla.f32 q3, q1, q9
vmla.f32 d4, d2, d21
vmla.f32 d5, d3, d20
bne 2b
add r1, r1, r6, lsl #2
subs r3, r3, #1
vadd.f32 d4, d4, d5
vadd.f32 d6, d6, d7
vpadd.f32 d5, d4, d6
vst1.32 {d5[0]}, [r0,:32]!
vst1.32 {d5[1]}, [r4,:32]!
bne 1b
pop {r4-r6,pc}
endfunc
/*
* Copyright (c) 2013 RISC OS Open Ltd
* Author: Ben Avison <bavison@riscosopen.org>
*
* 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/arm/asm.S"
POUT .req a1
PIN .req a2
PCOEF .req a3
OLDFPSCR .req a4
COUNTER .req ip
IN0 .req s4
IN1 .req s5
IN2 .req s6
IN3 .req s7
IN4 .req s0
IN5 .req s1
IN6 .req s2
IN7 .req s3
COEF0 .req s8 @ coefficient elements
COEF1 .req s9
COEF2 .req s10
COEF3 .req s11
COEF4 .req s12
COEF5 .req s13
COEF6 .req s14
COEF7 .req s15
ACCUM0 .req s16 @ double-buffered multiply-accumulate results
ACCUM4 .req s20
POST0 .req s24 @ do long-latency post-multiply in this vector in parallel
POST1 .req s25
POST2 .req s26
POST3 .req s27
.macro inner_loop decifactor, dir, tail, head
.ifc "\dir","up"
.set X, 0
.set Y, 4
.else
.set X, 4*JMAX*4 - 4
.set Y, -4
.endif
.ifnc "\head",""
vldr COEF0, [PCOEF, #X + (0*JMAX + 0) * Y]
vldr COEF1, [PCOEF, #X + (1*JMAX + 0) * Y]
vldr COEF2, [PCOEF, #X + (2*JMAX + 0) * Y]
vldr COEF3, [PCOEF, #X + (3*JMAX + 0) * Y]
.endif
.ifnc "\tail",""
vadd.f POST0, ACCUM0, ACCUM4 @ vector operation
.endif
.ifnc "\head",""
vmul.f ACCUM0, COEF0, IN0 @ vector = vector * scalar
vldr COEF4, [PCOEF, #X + (0*JMAX + 1) * Y]
vldr COEF5, [PCOEF, #X + (1*JMAX + 1) * Y]
vldr COEF6, [PCOEF, #X + (2*JMAX + 1) * Y]
.endif
.ifnc "\head",""
vldr COEF7, [PCOEF, #X + (3*JMAX + 1) * Y]
.ifc "\tail",""
vmul.f ACCUM4, COEF4, IN1 @ vector operation
.endif
vldr COEF0, [PCOEF, #X + (0*JMAX + 2) * Y]
vldr COEF1, [PCOEF, #X + (1*JMAX + 2) * Y]
.ifnc "\tail",""
vmul.f ACCUM4, COEF4, IN1 @ vector operation
.endif
vldr COEF2, [PCOEF, #X + (2*JMAX + 2) * Y]
vldr COEF3, [PCOEF, #X + (3*JMAX + 2) * Y]
.endif
.ifnc "\tail",""
vstmia POUT!, {POST0-POST3}
.endif
.ifnc "\head",""
vmla.f ACCUM0, COEF0, IN2 @ vector = vector * scalar
vldr COEF4, [PCOEF, #X + (0*JMAX + 3) * Y]
vldr COEF5, [PCOEF, #X + (1*JMAX + 3) * Y]
vldr COEF6, [PCOEF, #X + (2*JMAX + 3) * Y]
vldr COEF7, [PCOEF, #X + (3*JMAX + 3) * Y]
vmla.f ACCUM4, COEF4, IN3 @ vector = vector * scalar
.if \decifactor == 32
vldr COEF0, [PCOEF, #X + (0*JMAX + 4) * Y]
vldr COEF1, [PCOEF, #X + (1*JMAX + 4) * Y]
vldr COEF2, [PCOEF, #X + (2*JMAX + 4) * Y]
vldr COEF3, [PCOEF, #X + (3*JMAX + 4) * Y]
vmla.f ACCUM0, COEF0, IN4 @ vector = vector * scalar
vldr COEF4, [PCOEF, #X + (0*JMAX + 5) * Y]
vldr COEF5, [PCOEF, #X + (1*JMAX + 5) * Y]
vldr COEF6, [PCOEF, #X + (2*JMAX + 5) * Y]
vldr COEF7, [PCOEF, #X + (3*JMAX + 5) * Y]
vmla.f ACCUM4, COEF4, IN5 @ vector = vector * scalar
vldr COEF0, [PCOEF, #X + (0*JMAX + 6) * Y]
vldr COEF1, [PCOEF, #X + (1*JMAX + 6) * Y]
vldr COEF2, [PCOEF, #X + (2*JMAX + 6) * Y]
vldr COEF3, [PCOEF, #X + (3*JMAX + 6) * Y]
vmla.f ACCUM0, COEF0, IN6 @ vector = vector * scalar
vldr COEF4, [PCOEF, #X + (0*JMAX + 7) * Y]
vldr COEF5, [PCOEF, #X + (1*JMAX + 7) * Y]
vldr COEF6, [PCOEF, #X + (2*JMAX + 7) * Y]
vldr COEF7, [PCOEF, #X + (3*JMAX + 7) * Y]
vmla.f ACCUM4, COEF4, IN7 @ vector = vector * scalar
.endif
.endif
.endm
.macro dca_lfe_fir decifactor
function ff_dca_lfe_fir\decifactor\()_vfp, export=1
fmrx OLDFPSCR, FPSCR
ldr ip, =0x03030000 @ RunFast mode, short vectors of length 4, stride 1
fmxr FPSCR, ip
vldr IN0, [PIN, #-0*4]
vldr IN1, [PIN, #-1*4]
vldr IN2, [PIN, #-2*4]
vldr IN3, [PIN, #-3*4]
.if \decifactor == 32
.set JMAX, 8
vpush {s16-s31}
vldr IN4, [PIN, #-4*4]
vldr IN5, [PIN, #-5*4]
vldr IN6, [PIN, #-6*4]
vldr IN7, [PIN, #-7*4]
.else
.set JMAX, 4
vpush {s16-s27}
.endif
mov COUNTER, #\decifactor/4 - 1
inner_loop \decifactor, up,, head
1: add PCOEF, PCOEF, #4*JMAX*4
subs COUNTER, COUNTER, #1
inner_loop \decifactor, up, tail, head
bne 1b
inner_loop \decifactor, up, tail
mov COUNTER, #\decifactor/4 - 1
inner_loop \decifactor, down,, head
1: sub PCOEF, PCOEF, #4*JMAX*4
subs COUNTER, COUNTER, #1
inner_loop \decifactor, down, tail, head
bne 1b
inner_loop \decifactor, down, tail
.if \decifactor == 32
vpop {s16-s31}
.else
vpop {s16-s27}
.endif
fmxr FPSCR, OLDFPSCR
bx lr
endfunc
.endm
dca_lfe_fir 64
.ltorg
dca_lfe_fir 32
.unreq POUT
.unreq PIN
.unreq PCOEF
.unreq OLDFPSCR
.unreq COUNTER
.unreq IN0
.unreq IN1
.unreq IN2
.unreq IN3
.unreq IN4
.unreq IN5
.unreq IN6
.unreq IN7
.unreq COEF0
.unreq COEF1
.unreq COEF2
.unreq COEF3
.unreq COEF4
.unreq COEF5
.unreq COEF6
.unreq COEF7
.unreq ACCUM0
.unreq ACCUM4
.unreq POST0
.unreq POST1
.unreq POST2
.unreq POST3
IN .req a1
SBACT .req a2
OLDFPSCR .req a3
IMDCT .req a4
WINDOW .req v1
OUT .req v2
BUF .req v3
SCALEINT .req v4 @ only used in softfp case
COUNT .req v5
SCALE .req s0
/* Stack layout differs in softfp and hardfp cases:
*
* hardfp
* fp -> 6 arg words saved by caller
* a3,a4,v1-v3,v5,fp,lr on entry (a3 just to pad to 8 bytes)
* s16-s23 on entry
* align 16
* buf -> 8*32*4 bytes buffer
* s0 on entry
* sp -> 3 arg words for callee
*
* softfp
* fp -> 7 arg words saved by caller
* a4,v1-v5,fp,lr on entry
* s16-s23 on entry
* align 16
* buf -> 8*32*4 bytes buffer
* sp -> 4 arg words for callee
*/
/* void ff_dca_qmf_32_subbands_vfp(float samples_in[32][8], int sb_act,
* SynthFilterContext *synth, FFTContext *imdct,
* float (*synth_buf_ptr)[512],
* int *synth_buf_offset, float (*synth_buf2)[32],
* const float (*window)[512], float *samples_out,
* float (*raXin)[32], float scale);
*/
function ff_dca_qmf_32_subbands_vfp, export=1
VFP push {a3-a4,v1-v3,v5,fp,lr}
NOVFP push {a4,v1-v5,fp,lr}
add fp, sp, #8*4
vpush {s16-s23}
@ The buffer pointed at by raXin isn't big enough for us to do a
@ complete matrix transposition as we want to, so allocate an
@ alternative buffer from the stack. Align to 4 words for speed.
sub BUF, sp, #8*32*4
bic BUF, BUF, #15
mov sp, BUF
ldr lr, =0x03330000 @ RunFast mode, short vectors of length 4, stride 2
fmrx OLDFPSCR, FPSCR
fmxr FPSCR, lr
@ COUNT is used to count down 2 things at once:
@ bits 0-4 are the number of word pairs remaining in the output row
@ bits 5-31 are the number of words to copy (with possible negation)
@ from the source matrix before we start zeroing the remainder
mov COUNT, #(-4 << 5) + 16
adds COUNT, COUNT, SBACT, lsl #5
bmi 2f
1:
vldr s8, [IN, #(0*8+0)*4]
vldr s10, [IN, #(0*8+1)*4]
vldr s12, [IN, #(0*8+2)*4]
vldr s14, [IN, #(0*8+3)*4]
vldr s16, [IN, #(0*8+4)*4]
vldr s18, [IN, #(0*8+5)*4]
vldr s20, [IN, #(0*8+6)*4]
vldr s22, [IN, #(0*8+7)*4]
vneg.f s8, s8
vldr s9, [IN, #(1*8+0)*4]
vldr s11, [IN, #(1*8+1)*4]
vldr s13, [IN, #(1*8+2)*4]
vldr s15, [IN, #(1*8+3)*4]
vneg.f s16, s16
vldr s17, [IN, #(1*8+4)*4]
vldr s19, [IN, #(1*8+5)*4]
vldr s21, [IN, #(1*8+6)*4]
vldr s23, [IN, #(1*8+7)*4]
vstr d4, [BUF, #(0*32+0)*4]
vstr d5, [BUF, #(1*32+0)*4]
vstr d6, [BUF, #(2*32+0)*4]
vstr d7, [BUF, #(3*32+0)*4]
vstr d8, [BUF, #(4*32+0)*4]
vstr d9, [BUF, #(5*32+0)*4]
vstr d10, [BUF, #(6*32+0)*4]
vstr d11, [BUF, #(7*32+0)*4]
vldr s9, [IN, #(3*8+0)*4]
vldr s11, [IN, #(3*8+1)*4]
vldr s13, [IN, #(3*8+2)*4]
vldr s15, [IN, #(3*8+3)*4]
vldr s17, [IN, #(3*8+4)*4]
vldr s19, [IN, #(3*8+5)*4]
vldr s21, [IN, #(3*8+6)*4]
vldr s23, [IN, #(3*8+7)*4]
vneg.f s9, s9
vldr s8, [IN, #(2*8+0)*4]
vldr s10, [IN, #(2*8+1)*4]
vldr s12, [IN, #(2*8+2)*4]
vldr s14, [IN, #(2*8+3)*4]
vneg.f s17, s17
vldr s16, [IN, #(2*8+4)*4]
vldr s18, [IN, #(2*8+5)*4]
vldr s20, [IN, #(2*8+6)*4]
vldr s22, [IN, #(2*8+7)*4]
vstr d4, [BUF, #(0*32+2)*4]
vstr d5, [BUF, #(1*32+2)*4]
vstr d6, [BUF, #(2*32+2)*4]
vstr d7, [BUF, #(3*32+2)*4]
vstr d8, [BUF, #(4*32+2)*4]
vstr d9, [BUF, #(5*32+2)*4]
vstr d10, [BUF, #(6*32+2)*4]
vstr d11, [BUF, #(7*32+2)*4]
add IN, IN, #4*8*4
add BUF, BUF, #4*4
subs COUNT, COUNT, #(4 << 5) + 2
bpl 1b
2: @ Now deal with trailing < 4 samples
adds COUNT, COUNT, #3 << 5
bmi 4f @ sb_act was a multiple of 4
bics lr, COUNT, #0x1F
bne 3f
@ sb_act was n*4+1
vldr s8, [IN, #(0*8+0)*4]
vldr s10, [IN, #(0*8+1)*4]
vldr s12, [IN, #(0*8+2)*4]
vldr s14, [IN, #(0*8+3)*4]
vldr s16, [IN, #(0*8+4)*4]
vldr s18, [IN, #(0*8+5)*4]
vldr s20, [IN, #(0*8+6)*4]
vldr s22, [IN, #(0*8+7)*4]
vneg.f s8, s8
vldr s9, zero
vldr s11, zero
vldr s13, zero
vldr s15, zero
vneg.f s16, s16
vldr s17, zero
vldr s19, zero
vldr s21, zero
vldr s23, zero
vstr d4, [BUF, #(0*32+0)*4]
vstr d5, [BUF, #(1*32+0)*4]
vstr d6, [BUF, #(2*32+0)*4]
vstr d7, [BUF, #(3*32+0)*4]
vstr d8, [BUF, #(4*32+0)*4]
vstr d9, [BUF, #(5*32+0)*4]
vstr d10, [BUF, #(6*32+0)*4]
vstr d11, [BUF, #(7*32+0)*4]
add BUF, BUF, #2*4
sub COUNT, COUNT, #1
b 4f
3: @ sb_act was n*4+2 or n*4+3, so do the first 2
vldr s8, [IN, #(0*8+0)*4]
vldr s10, [IN, #(0*8+1)*4]
vldr s12, [IN, #(0*8+2)*4]
vldr s14, [IN, #(0*8+3)*4]
vldr s16, [IN, #(0*8+4)*4]
vldr s18, [IN, #(0*8+5)*4]
vldr s20, [IN, #(0*8+6)*4]
vldr s22, [IN, #(0*8+7)*4]
vneg.f s8, s8
vldr s9, [IN, #(1*8+0)*4]
vldr s11, [IN, #(1*8+1)*4]
vldr s13, [IN, #(1*8+2)*4]
vldr s15, [IN, #(1*8+3)*4]
vneg.f s16, s16
vldr s17, [IN, #(1*8+4)*4]
vldr s19, [IN, #(1*8+5)*4]
vldr s21, [IN, #(1*8+6)*4]
vldr s23, [IN, #(1*8+7)*4]
vstr d4, [BUF, #(0*32+0)*4]
vstr d5, [BUF, #(1*32+0)*4]
vstr d6, [BUF, #(2*32+0)*4]
vstr d7, [BUF, #(3*32+0)*4]
vstr d8, [BUF, #(4*32+0)*4]
vstr d9, [BUF, #(5*32+0)*4]
vstr d10, [BUF, #(6*32+0)*4]
vstr d11, [BUF, #(7*32+0)*4]
add BUF, BUF, #2*4
sub COUNT, COUNT, #(2 << 5) + 1
bics lr, COUNT, #0x1F
bne 4f
@ sb_act was n*4+3
vldr s8, [IN, #(2*8+0)*4]
vldr s10, [IN, #(2*8+1)*4]
vldr s12, [IN, #(2*8+2)*4]
vldr s14, [IN, #(2*8+3)*4]
vldr s16, [IN, #(2*8+4)*4]
vldr s18, [IN, #(2*8+5)*4]
vldr s20, [IN, #(2*8+6)*4]
vldr s22, [IN, #(2*8+7)*4]
vldr s9, zero
vldr s11, zero
vldr s13, zero
vldr s15, zero
vldr s17, zero
vldr s19, zero
vldr s21, zero
vldr s23, zero
vstr d4, [BUF, #(0*32+0)*4]
vstr d5, [BUF, #(1*32+0)*4]
vstr d6, [BUF, #(2*32+0)*4]
vstr d7, [BUF, #(3*32+0)*4]
vstr d8, [BUF, #(4*32+0)*4]
vstr d9, [BUF, #(5*32+0)*4]
vstr d10, [BUF, #(6*32+0)*4]
vstr d11, [BUF, #(7*32+0)*4]
add BUF, BUF, #2*4
sub COUNT, COUNT, #1
4: @ Now fill the remainder with 0
vldr s8, zero
vldr s9, zero
ands COUNT, COUNT, #0x1F
beq 6f
5: vstr d4, [BUF, #(0*32+0)*4]
vstr d4, [BUF, #(1*32+0)*4]
vstr d4, [BUF, #(2*32+0)*4]
vstr d4, [BUF, #(3*32+0)*4]
vstr d4, [BUF, #(4*32+0)*4]
vstr d4, [BUF, #(5*32+0)*4]
vstr d4, [BUF, #(6*32+0)*4]
vstr d4, [BUF, #(7*32+0)*4]
add BUF, BUF, #2*4
subs COUNT, COUNT, #1
bne 5b
6:
fmxr FPSCR, OLDFPSCR
ldr WINDOW, [fp, #3*4]
ldr OUT, [fp, #4*4]
sub BUF, BUF, #32*4
NOVFP ldr SCALEINT, [fp, #6*4]
mov COUNT, #8
VFP vpush {SCALE}
VFP sub sp, sp, #3*4
NOVFP sub sp, sp, #4*4
7:
VFP ldr a1, [fp, #-7*4] @ imdct
NOVFP ldr a1, [fp, #-8*4]
ldmia fp, {a2-a4}
VFP stmia sp, {WINDOW, OUT, BUF}
NOVFP stmia sp, {WINDOW, OUT, BUF, SCALEINT}
VFP vldr SCALE, [sp, #3*4]
bl X(ff_synth_filter_float_vfp)
add OUT, OUT, #32*4
add BUF, BUF, #32*4
subs COUNT, COUNT, #1
bne 7b
A sub sp, fp, #(8+8)*4
T sub fp, fp, #(8+8)*4
T mov sp, fp
vpop {s16-s23}
VFP pop {a3-a4,v1-v3,v5,fp,pc}
NOVFP pop {a4,v1-v5,fp,pc}
endfunc
.unreq IN
.unreq SBACT
.unreq OLDFPSCR
.unreq IMDCT
.unreq WINDOW
.unreq OUT
.unreq BUF
.unreq SCALEINT
.unreq COUNT
.unreq SCALE
.align 2
zero: .word 0
......@@ -27,282 +27,8 @@
#include <stdint.h>
#include "libavutil/float_dsp.h"
#include "libavutil/internal.h"
#include "avcodec.h"
#include "dcadsp.h"
#include "fmtconvert.h"
#include "get_bits.h"
#define DCA_PRIM_CHANNELS_MAX (7)
#define DCA_ABITS_MAX (32) /* Should be 28 */
#define DCA_SUBSUBFRAMES_MAX (4)
#define DCA_SUBFRAMES_MAX (16)
#define DCA_BLOCKS_MAX (16)
#define DCA_LFE_MAX (3)
#define DCA_CHSETS_MAX (4)
#define DCA_CHSET_CHANS_MAX (8)
#define DCA_PRIM_CHANNELS_MAX (7)
#define DCA_ABITS_MAX (32) /* Should be 28 */
#define DCA_SUBSUBFRAMES_MAX (4)
#define DCA_SUBFRAMES_MAX (16)
#define DCA_BLOCKS_MAX (16)
#define DCA_LFE_MAX (3)
#define DCA_XLL_FBANDS_MAX (4)
#define DCA_XLL_SEGMENTS_MAX (16)
#define DCA_XLL_CHSETS_MAX (16)
#define DCA_XLL_CHANNELS_MAX (16)
#define DCA_XLL_AORDER_MAX (15)
/* Arbitrary limit; not sure what the maximum really is, but much larger. */
#define DCA_XLL_DMIX_NCOEFFS_MAX (18)
#define DCA_MAX_FRAME_SIZE 16384
#define DCA_MAX_EXSS_HEADER_SIZE 4096
#define DCA_BUFFER_PADDING_SIZE 1024
enum DCAExtensionMask {
DCA_EXT_CORE = 0x001, ///< core in core substream
DCA_EXT_XXCH = 0x002, ///< XXCh channels extension in core substream
DCA_EXT_X96 = 0x004, ///< 96/24 extension in core substream
DCA_EXT_XCH = 0x008, ///< XCh channel extension in core substream
DCA_EXT_EXSS_CORE = 0x010, ///< core in ExSS (extension substream)
DCA_EXT_EXSS_XBR = 0x020, ///< extended bitrate extension in ExSS
DCA_EXT_EXSS_XXCH = 0x040, ///< XXCh channels extension in ExSS
DCA_EXT_EXSS_X96 = 0x080, ///< 96/24 extension in ExSS
DCA_EXT_EXSS_LBR = 0x100, ///< low bitrate component in ExSS
DCA_EXT_EXSS_XLL = 0x200, ///< lossless extension in ExSS
};
typedef struct XllChSetSubHeader {
int channels; ///< number of channels in channel set, at most 16
int residual_encode; ///< residual channel encoding
int bit_resolution; ///< input sample bit-width
int bit_width; ///< original input sample bit-width
int sampling_frequency; ///< sampling frequency
int samp_freq_interp; ///< sampling frequency interpolation multiplier
int replacement_set; ///< replacement channel set group
int active_replace_set; ///< current channel set is active channel set
int primary_ch_set;
int downmix_coeff_code_embedded;
int downmix_embedded;
int downmix_type;
int hier_chset; ///< hierarchical channel set
int downmix_ncoeffs;
int downmix_coeffs[DCA_XLL_DMIX_NCOEFFS_MAX];
int ch_mask_enabled;
int ch_mask;
int mapping_coeffs_present;
int num_freq_bands;
/* m_nOrigChanOrder */
uint8_t orig_chan_order[DCA_XLL_FBANDS_MAX][DCA_XLL_CHANNELS_MAX];
uint8_t orig_chan_order_inv[DCA_XLL_FBANDS_MAX][DCA_XLL_CHANNELS_MAX];
/* Coefficients for channel pairs (at most 8), m_anPWChPairsCoeffs */
int8_t pw_ch_pairs_coeffs[DCA_XLL_FBANDS_MAX][DCA_XLL_CHANNELS_MAX/2];
/* m_nCurrHighestLPCOrder */
uint8_t adapt_order_max[DCA_XLL_FBANDS_MAX];
/* m_pnAdaptPredOrder */
uint8_t adapt_order[DCA_XLL_FBANDS_MAX][DCA_XLL_CHANNELS_MAX];
/* m_pnFixedPredOrder */
uint8_t fixed_order[DCA_XLL_FBANDS_MAX][DCA_XLL_CHANNELS_MAX];
/* m_pnLPCReflCoeffsQInd, unsigned version */
uint8_t lpc_refl_coeffs_q_ind[DCA_XLL_FBANDS_MAX]
[DCA_XLL_CHANNELS_MAX][DCA_XLL_AORDER_MAX];
int lsb_fsize[DCA_XLL_FBANDS_MAX];
int8_t scalable_lsbs[DCA_XLL_FBANDS_MAX][DCA_XLL_CHANNELS_MAX];
int8_t bit_width_adj_per_ch[DCA_XLL_FBANDS_MAX][DCA_XLL_CHANNELS_MAX];
} XllChSetSubHeader;
typedef struct XllNavi {
GetBitContext gb; // Context for parsing the data segments
unsigned band_size[DCA_XLL_FBANDS_MAX];
unsigned segment_size[DCA_XLL_FBANDS_MAX][DCA_XLL_SEGMENTS_MAX];
unsigned chset_size[DCA_XLL_FBANDS_MAX][DCA_XLL_SEGMENTS_MAX][DCA_XLL_CHSETS_MAX];
} XllNavi;
typedef struct QMF64_table {
float dct4_coeff[32][32];
float dct2_coeff[32][32];
float rcos[32];
float rsin[32];
} QMF64_table;
/* Primary audio coding header */
typedef struct DCAAudioHeader {
int subband_activity[DCA_PRIM_CHANNELS_MAX]; ///< subband activity count
int vq_start_subband[DCA_PRIM_CHANNELS_MAX]; ///< high frequency vq start subband
int joint_intensity[DCA_PRIM_CHANNELS_MAX]; ///< joint intensity coding index
int transient_huffman[DCA_PRIM_CHANNELS_MAX]; ///< transient mode code book
int scalefactor_huffman[DCA_PRIM_CHANNELS_MAX]; ///< scale factor code book
int bitalloc_huffman[DCA_PRIM_CHANNELS_MAX]; ///< bit allocation quantizer select
int quant_index_huffman[DCA_PRIM_CHANNELS_MAX][DCA_ABITS_MAX]; ///< quantization index codebook select
uint32_t scalefactor_adj[DCA_PRIM_CHANNELS_MAX][DCA_ABITS_MAX]; ///< scale factor adjustment
int subframes; ///< number of subframes
int total_channels; ///< number of channels including extensions
int prim_channels; ///< number of primary audio channels
} DCAAudioHeader;
typedef struct DCAChan {
DECLARE_ALIGNED(32, int32_t, subband_samples)[DCA_BLOCKS_MAX][DCA_SUBBANDS][SAMPLES_PER_SUBBAND];
/* Subband samples history (for ADPCM) */
DECLARE_ALIGNED(32, int32_t, subband_samples_hist)[DCA_SUBBANDS][4];
int hist_index;
/* Half size is sufficient for core decoding, but for 96 kHz data
* we need QMF with 64 subbands and 1024 samples. */
DECLARE_ALIGNED(32, float, subband_fir_hist)[1024];
DECLARE_ALIGNED(32, float, subband_fir_noidea)[64];
/* Primary audio coding side information */
int prediction_mode[DCA_SUBBANDS]; ///< prediction mode (ADPCM used or not)
int prediction_vq[DCA_SUBBANDS]; ///< prediction VQ coefs
int bitalloc[DCA_SUBBANDS]; ///< bit allocation index
int transition_mode[DCA_SUBBANDS]; ///< transition mode (transients)
int32_t scale_factor[DCA_SUBBANDS][2];///< scale factors (2 if transient)
int joint_huff; ///< joint subband scale factors codebook
int joint_scale_factor[DCA_SUBBANDS]; ///< joint subband scale factors
int32_t high_freq_vq[DCA_SUBBANDS]; ///< VQ encoded high frequency subbands
} DCAChan;
typedef struct DCAContext {
const AVClass *class; ///< class for AVOptions
AVCodecContext *avctx;
/* Frame header */
int frame_type; ///< type of the current frame
int samples_deficit; ///< deficit sample count
int crc_present; ///< crc is present in the bitstream
int sample_blocks; ///< number of PCM sample blocks
int frame_size; ///< primary frame byte size
int amode; ///< audio channels arrangement
int sample_rate; ///< audio sampling rate
int bit_rate; ///< transmission bit rate
int bit_rate_index; ///< transmission bit rate index
int dynrange; ///< embedded dynamic range flag
int timestamp; ///< embedded time stamp flag
int aux_data; ///< auxiliary data flag
int hdcd; ///< source material is mastered in HDCD
int ext_descr; ///< extension audio descriptor flag
int ext_coding; ///< extended coding flag
int aspf; ///< audio sync word insertion flag
int lfe; ///< low frequency effects flag
int predictor_history; ///< predictor history flag
int header_crc; ///< header crc check bytes
int multirate_inter; ///< multirate interpolator switch
int version; ///< encoder software revision
int copy_history; ///< copy history
int source_pcm_res; ///< source pcm resolution
int front_sum; ///< front sum/difference flag
int surround_sum; ///< surround sum/difference flag
int dialog_norm; ///< dialog normalisation parameter
/* Primary audio coding header */
DCAAudioHeader audio_header;
/* Primary audio coding side information */
int subsubframes[DCA_SUBFRAMES_MAX]; ///< number of subsubframes
int partial_samples[DCA_SUBFRAMES_MAX]; ///< partial subsubframe samples count
float downmix_coef[DCA_PRIM_CHANNELS_MAX + 1][2]; ///< stereo downmix coefficients
int dynrange_coef; ///< dynamic range coefficient
/* Core substream's embedded downmix coefficients (cf. ETSI TS 102 114 V1.4.1)
* Input: primary audio channels (incl. LFE if present)
* Output: downmix audio channels (up to 4, no LFE) */
uint8_t core_downmix; ///< embedded downmix coefficients available
uint8_t core_downmix_amode; ///< audio channel arrangement of embedded downmix
uint16_t core_downmix_codes[DCA_PRIM_CHANNELS_MAX + 1][4]; ///< embedded downmix coefficients (9-bit codes)
float lfe_data[2 * DCA_LFE_MAX * (DCA_BLOCKS_MAX + 4)]; ///< Low frequency effect data
int lfe_scale_factor;
/* Subband samples history (for ADPCM) */
DECLARE_ALIGNED(32, float, raXin)[32];
DCAChan dca_chan[DCA_PRIM_CHANNELS_MAX];
int output; ///< type of output
float *samples_chanptr[DCA_PRIM_CHANNELS_MAX + 1];
float *extra_channels[DCA_PRIM_CHANNELS_MAX + 1];
uint8_t *extra_channels_buffer;
unsigned int extra_channels_buffer_size;
uint8_t dca_buffer[DCA_MAX_FRAME_SIZE + DCA_MAX_EXSS_HEADER_SIZE + DCA_BUFFER_PADDING_SIZE];
int dca_buffer_size; ///< how much data is in the dca_buffer
const int8_t *channel_order_tab; ///< channel reordering table, lfe and non lfe
GetBitContext gb;
/* Current position in DCA frame */
int current_subframe;
int current_subsubframe;
int core_ext_mask; ///< present extensions in the core substream
int exss_ext_mask; ///< Non-core extensions
/* XCh extension information */
int xch_present; ///< XCh extension present and valid
int xch_base_channel; ///< index of first (only) channel containing XCH data
int xch_disable; ///< whether the XCh extension should be decoded or not
/* XXCH extension information */
int xxch_chset;
int xxch_nbits_spk_mask;
uint32_t xxch_core_spkmask;
uint32_t xxch_spk_masks[4]; /* speaker masks, last element is core mask */
int xxch_chset_nch[4];
float xxch_dmix_sf[DCA_CHSETS_MAX];
uint32_t xxch_dmix_embedded; /* lower layer has mix pre-embedded, per chset */
float xxch_dmix_coeff[DCA_PRIM_CHANNELS_MAX][32]; /* worst case sizing */
int8_t xxch_order_tab[32];
int8_t lfe_index;
/* XLL extension information */
int xll_disable;
int xll_nch_sets; ///< number of channel sets per frame
int xll_channels; ///< total number of channels (in all channel sets)
int xll_residual_channels; ///< number of residual channels
int xll_segments; ///< number of segments per frame
int xll_log_smpl_in_seg; ///< supposedly this is "nBits4SamplLoci"
int xll_smpl_in_seg; ///< samples in segment per one frequency band for the first channel set
int xll_bits4seg_size; ///< number of bits used to read segment size
int xll_banddata_crc; ///< presence of CRC16 within each frequency band
int xll_scalable_lsb;
int xll_bits4ch_mask; ///< channel position mask
int xll_fixed_lsb_width;
XllChSetSubHeader xll_chsets[DCA_XLL_CHSETS_MAX];
XllNavi xll_navi;
int *xll_sample_buf;
unsigned int xll_sample_buf_size;
/* ExSS header parser */
int static_fields; ///< static fields present
int mix_metadata; ///< mixing metadata present
int num_mix_configs; ///< number of mix out configurations
int mix_config_num_ch[4]; ///< number of channels in each mix out configuration
int profile;
int one2one_map_chtospkr;
int debug_flag; ///< used for suppressing repeated error messages output
AVFloatDSPContext *fdsp;
FFTContext imdct;
SynthFilterContext synth;
DCADSPContext dcadsp;
QMF64_table *qmf64_table;
FmtConvertContext fmt_conv;
} DCAContext;
#include "libavutil/intreadwrite.h"
extern av_export const uint32_t avpriv_dca_sample_rates[16];
......@@ -310,15 +36,6 @@ extern av_export const uint32_t avpriv_dca_sample_rates[16];
* Convert bitstream to one representation based on sync marker
*/
int avpriv_dca_convert_bitstream(const uint8_t *src, int src_size, uint8_t *dst,
int max_size);
int ff_dca_xbr_parse_frame(DCAContext *s);
int ff_dca_xxch_decode_frame(DCAContext *s);
void ff_dca_exss_parse_header(DCAContext *s);
int ff_dca_xll_decode_header(DCAContext *s);
int ff_dca_xll_decode_navi(DCAContext *s, int asset_end);
int ff_dca_xll_decode_audio(DCAContext *s, AVFrame *frame);
int max_size);
#endif /* AVCODEC_DCA_H */
/*
* DCA ExSS extension
*
* 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/common.h"
#include "libavutil/log.h"
#include "dca.h"
#include "dca_syncwords.h"
#include "get_bits.h"
/* extensions that reside in core substream */
#define DCA_CORE_EXTS (DCA_EXT_XCH | DCA_EXT_XXCH | DCA_EXT_X96)
/* these are unconfirmed but should be mostly correct */
enum DCAExSSSpeakerMask {
DCA_EXSS_FRONT_CENTER = 0x0001,
DCA_EXSS_FRONT_LEFT_RIGHT = 0x0002,
DCA_EXSS_SIDE_REAR_LEFT_RIGHT = 0x0004,
DCA_EXSS_LFE = 0x0008,
DCA_EXSS_REAR_CENTER = 0x0010,
DCA_EXSS_FRONT_HIGH_LEFT_RIGHT = 0x0020,
DCA_EXSS_REAR_LEFT_RIGHT = 0x0040,
DCA_EXSS_FRONT_HIGH_CENTER = 0x0080,
DCA_EXSS_OVERHEAD = 0x0100,
DCA_EXSS_CENTER_LEFT_RIGHT = 0x0200,
DCA_EXSS_WIDE_LEFT_RIGHT = 0x0400,
DCA_EXSS_SIDE_LEFT_RIGHT = 0x0800,
DCA_EXSS_LFE2 = 0x1000,
DCA_EXSS_SIDE_HIGH_LEFT_RIGHT = 0x2000,
DCA_EXSS_REAR_HIGH_CENTER = 0x4000,
DCA_EXSS_REAR_HIGH_LEFT_RIGHT = 0x8000,
};
/**
* Return the number of channels in an ExSS speaker mask (HD)
*/
static int dca_exss_mask2count(int mask)
{
/* count bits that mean speaker pairs twice */
return av_popcount(mask) +
av_popcount(mask & (DCA_EXSS_CENTER_LEFT_RIGHT |
DCA_EXSS_FRONT_LEFT_RIGHT |
DCA_EXSS_FRONT_HIGH_LEFT_RIGHT |
DCA_EXSS_WIDE_LEFT_RIGHT |
DCA_EXSS_SIDE_LEFT_RIGHT |
DCA_EXSS_SIDE_HIGH_LEFT_RIGHT |
DCA_EXSS_SIDE_REAR_LEFT_RIGHT |
DCA_EXSS_REAR_LEFT_RIGHT |
DCA_EXSS_REAR_HIGH_LEFT_RIGHT));
}
/**
* Skip mixing coefficients of a single mix out configuration (HD)
*/
static void dca_exss_skip_mix_coeffs(GetBitContext *gb, int channels, int out_ch)
{
int i;
for (i = 0; i < channels; i++) {
int mix_map_mask = get_bits(gb, out_ch);
int num_coeffs = av_popcount(mix_map_mask);
skip_bits_long(gb, num_coeffs * 6);
}
}
/**
* Parse extension substream asset header (HD)
*/
static int dca_exss_parse_asset_header(DCAContext *s)
{
int header_pos = get_bits_count(&s->gb);
int header_size;
int channels = 0;
int embedded_stereo = 0;
int embedded_6ch = 0;
int drc_code_present;
int extensions_mask = 0;
int i, j;
if (get_bits_left(&s->gb) < 16)
return AVERROR_INVALIDDATA;
/* We will parse just enough to get to the extensions bitmask with which
* we can set the profile value. */
header_size = get_bits(&s->gb, 9) + 1;
skip_bits(&s->gb, 3); // asset index
if (s->static_fields) {
if (get_bits1(&s->gb))
skip_bits(&s->gb, 4); // asset type descriptor
if (get_bits1(&s->gb))
skip_bits_long(&s->gb, 24); // language descriptor
if (get_bits1(&s->gb)) {
/* How can one fit 1024 bytes of text here if the maximum value
* for the asset header size field above was 512 bytes? */
int text_length = get_bits(&s->gb, 10) + 1;
if (get_bits_left(&s->gb) < text_length * 8)
return AVERROR_INVALIDDATA;
skip_bits_long(&s->gb, text_length * 8); // info text
}
skip_bits(&s->gb, 5); // bit resolution - 1
skip_bits(&s->gb, 4); // max sample rate code
channels = get_bits(&s->gb, 8) + 1;
s->one2one_map_chtospkr = get_bits1(&s->gb);
if (s->one2one_map_chtospkr) {
int spkr_remap_sets;
int spkr_mask_size = 16;
int num_spkrs[7];
if (channels > 2)
embedded_stereo = get_bits1(&s->gb);
if (channels > 6)
embedded_6ch = get_bits1(&s->gb);
if (get_bits1(&s->gb)) {
spkr_mask_size = (get_bits(&s->gb, 2) + 1) << 2;
skip_bits(&s->gb, spkr_mask_size); // spkr activity mask
}
spkr_remap_sets = get_bits(&s->gb, 3);
for (i = 0; i < spkr_remap_sets; i++) {
/* std layout mask for each remap set */
num_spkrs[i] = dca_exss_mask2count(get_bits(&s->gb, spkr_mask_size));
}
for (i = 0; i < spkr_remap_sets; i++) {
int num_dec_ch_remaps = get_bits(&s->gb, 5) + 1;
if (get_bits_left(&s->gb) < 0)
return AVERROR_INVALIDDATA;
for (j = 0; j < num_spkrs[i]; j++) {
int remap_dec_ch_mask = get_bits_long(&s->gb, num_dec_ch_remaps);
int num_dec_ch = av_popcount(remap_dec_ch_mask);
skip_bits_long(&s->gb, num_dec_ch * 5); // remap codes
}
}
} else {
skip_bits(&s->gb, 3); // representation type
}
}
drc_code_present = get_bits1(&s->gb);
if (drc_code_present)
get_bits(&s->gb, 8); // drc code
if (get_bits1(&s->gb))
skip_bits(&s->gb, 5); // dialog normalization code
if (drc_code_present && embedded_stereo)
get_bits(&s->gb, 8); // drc stereo code
if (s->mix_metadata && get_bits1(&s->gb)) {
skip_bits(&s->gb, 1); // external mix
skip_bits(&s->gb, 6); // post mix gain code
if (get_bits(&s->gb, 2) != 3) // mixer drc code
skip_bits(&s->gb, 3); // drc limit
else
skip_bits(&s->gb, 8); // custom drc code
if (get_bits1(&s->gb)) // channel specific scaling
for (i = 0; i < s->num_mix_configs; i++)
skip_bits_long(&s->gb, s->mix_config_num_ch[i] * 6); // scale codes
else
skip_bits_long(&s->gb, s->num_mix_configs * 6); // scale codes
for (i = 0; i < s->num_mix_configs; i++) {
if (get_bits_left(&s->gb) < 0)
return AVERROR_INVALIDDATA;
dca_exss_skip_mix_coeffs(&s->gb, channels, s->mix_config_num_ch[i]);
if (embedded_6ch)
dca_exss_skip_mix_coeffs(&s->gb, 6, s->mix_config_num_ch[i]);
if (embedded_stereo)
dca_exss_skip_mix_coeffs(&s->gb, 2, s->mix_config_num_ch[i]);
}
}
switch (get_bits(&s->gb, 2)) {
case 0:
extensions_mask = get_bits(&s->gb, 12);
break;
case 1:
extensions_mask = DCA_EXT_EXSS_XLL;
break;
case 2:
extensions_mask = DCA_EXT_EXSS_LBR;
break;
case 3:
extensions_mask = 0; /* aux coding */
break;
}
/* not parsed further, we were only interested in the extensions mask */
if (get_bits_left(&s->gb) < 0)
return AVERROR_INVALIDDATA;
if (get_bits_count(&s->gb) - header_pos > header_size * 8) {
av_log(s->avctx, AV_LOG_WARNING, "Asset header size mismatch.\n");
return AVERROR_INVALIDDATA;
}
skip_bits_long(&s->gb, header_pos + header_size * 8 - get_bits_count(&s->gb));
if (extensions_mask & DCA_EXT_EXSS_XLL)
s->profile = FF_PROFILE_DTS_HD_MA;
else if (extensions_mask & (DCA_EXT_EXSS_XBR | DCA_EXT_EXSS_X96 |
DCA_EXT_EXSS_XXCH))
s->profile = FF_PROFILE_DTS_HD_HRA;
if (!(extensions_mask & DCA_EXT_CORE))
av_log(s->avctx, AV_LOG_WARNING, "DTS core detection mismatch.\n");
if ((extensions_mask & DCA_CORE_EXTS) != s->core_ext_mask)
av_log(s->avctx, AV_LOG_WARNING,
"DTS extensions detection mismatch (%d, %d)\n",
extensions_mask & DCA_CORE_EXTS, s->core_ext_mask);
return 0;
}
/**
* Parse extension substream header (HD)
*/
void ff_dca_exss_parse_header(DCAContext *s)
{
int asset_size[8];
int ss_index;
int blownup;
int num_audiop = 1;
int num_assets = 1;
int active_ss_mask[8];
int i, j;
int start_pos;
int hdrsize;
uint32_t mkr;
if (get_bits_left(&s->gb) < 52)
return;
start_pos = get_bits_count(&s->gb) - 32;
skip_bits(&s->gb, 8); // user data
ss_index = get_bits(&s->gb, 2);
blownup = get_bits1(&s->gb);
hdrsize = get_bits(&s->gb, 8 + 4 * blownup) + 1; // header_size
skip_bits(&s->gb, 16 + 4 * blownup); // hd_size
s->static_fields = get_bits1(&s->gb);
if (s->static_fields) {
skip_bits(&s->gb, 2); // reference clock code
skip_bits(&s->gb, 3); // frame duration code
if (get_bits1(&s->gb))
skip_bits_long(&s->gb, 36); // timestamp
/* a single stream can contain multiple audio assets that can be
* combined to form multiple audio presentations */
num_audiop = get_bits(&s->gb, 3) + 1;
if (num_audiop > 1) {
avpriv_request_sample(s->avctx,
"Multiple DTS-HD audio presentations");
/* ignore such streams for now */
return;
}
num_assets = get_bits(&s->gb, 3) + 1;
if (num_assets > 1) {
avpriv_request_sample(s->avctx, "Multiple DTS-HD audio assets");
/* ignore such streams for now */
return;
}
for (i = 0; i < num_audiop; i++)
active_ss_mask[i] = get_bits(&s->gb, ss_index + 1);
for (i = 0; i < num_audiop; i++)
for (j = 0; j <= ss_index; j++)
if (active_ss_mask[i] & (1 << j))
skip_bits(&s->gb, 8); // active asset mask
s->mix_metadata = get_bits1(&s->gb);
if (s->mix_metadata) {
int mix_out_mask_size;
skip_bits(&s->gb, 2); // adjustment level
mix_out_mask_size = (get_bits(&s->gb, 2) + 1) << 2;
s->num_mix_configs = get_bits(&s->gb, 2) + 1;
for (i = 0; i < s->num_mix_configs; i++) {
int mix_out_mask = get_bits(&s->gb, mix_out_mask_size);
s->mix_config_num_ch[i] = dca_exss_mask2count(mix_out_mask);
}
}
}
av_assert0(num_assets > 0); // silence a warning
for (i = 0; i < num_assets; i++)
asset_size[i] = get_bits_long(&s->gb, 16 + 4 * blownup) + 1;
for (i = 0; i < num_assets; i++) {
if (dca_exss_parse_asset_header(s))
return;
}
j = get_bits_count(&s->gb);
if (start_pos + hdrsize * 8 > j)
skip_bits_long(&s->gb, start_pos + hdrsize * 8 - j);
for (i = 0; i < num_assets; i++) {
int end_pos;
start_pos = get_bits_count(&s->gb);
end_pos = start_pos + asset_size[i] * 8;
mkr = get_bits_long(&s->gb, 32);
/* parse extensions that we know about */
switch (mkr) {
case DCA_SYNCWORD_XBR:
ff_dca_xbr_parse_frame(s);
break;
case DCA_SYNCWORD_XXCH:
ff_dca_xxch_decode_frame(s);
s->core_ext_mask |= DCA_EXT_XXCH; /* xxx use for chan reordering */
break;
case DCA_SYNCWORD_XLL:
if (s->xll_disable) {
av_log(s->avctx, AV_LOG_DEBUG,
"DTS-XLL: ignoring XLL extension\n");
break;
}
av_log(s->avctx, AV_LOG_DEBUG,
"DTS-XLL: decoding XLL extension\n");
if (ff_dca_xll_decode_header(s) == 0 &&
ff_dca_xll_decode_navi(s, end_pos) == 0)
s->exss_ext_mask |= DCA_EXT_EXSS_XLL;
break;
default:
av_log(s->avctx, AV_LOG_DEBUG,
"DTS-ExSS: unknown marker = 0x%08x\n", mkr);
}
/* skip to end of block */
j = get_bits_count(&s->gb);
if (j > end_pos)
av_log(s->avctx, AV_LOG_ERROR,
"DTS-ExSS: Processed asset too long.\n");
if (j < end_pos)
skip_bits_long(&s->gb, end_pos - j);
}
}
/*
* DCA XLL extension
*
* Copyright (C) 2012 Paul B Mahol
* Copyright (C) 2014 Niels Möller
*
* 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/attributes.h"
#include "libavutil/common.h"
#include "libavutil/internal.h"
#include "avcodec.h"
#include "dca.h"
#include "dcadata.h"
#include "get_bits.h"
#include "unary.h"
/* Sign as bit 0 */
static inline int get_bits_sm(GetBitContext *s, unsigned n)
{
int x = get_bits(s, n);
if (x & 1)
return -(x >> 1) - 1;
else
return x >> 1;
}
/* Return -1 on error. */
static int32_t get_dmix_coeff(DCAContext *s, int inverse)
{
unsigned code = get_bits(&s->gb, 9);
int32_t sign = (int32_t) (code >> 8) - 1;
unsigned idx = code & 0xff;
int inv_offset = FF_DCA_DMIXTABLE_SIZE -FF_DCA_INV_DMIXTABLE_SIZE;
if (idx >= FF_DCA_DMIXTABLE_SIZE) {
av_log(s->avctx, AV_LOG_ERROR,
"XLL: Invalid channel set downmix code %x\n", code);
return -1;
} else if (!inverse) {
return (ff_dca_dmixtable[idx] ^ sign) - sign;
} else if (idx < inv_offset) {
av_log(s->avctx, AV_LOG_ERROR,
"XLL: Invalid channel set inverse downmix code %x\n", code);
return -1;
} else {
return (ff_dca_inv_dmixtable[idx - inv_offset] ^ sign) - sign;
}
}
static int32_t dca_get_dmix_coeff(DCAContext *s)
{
return get_dmix_coeff(s, 0);
}
static int32_t dca_get_inv_dmix_coeff(DCAContext *s)
{
return get_dmix_coeff(s, 1);
}
/* parse XLL header */
int ff_dca_xll_decode_header(DCAContext *s)
{
int hdr_pos, hdr_size;
av_unused int version, frame_size;
int i, chset_index;
/* get bit position of sync header */
hdr_pos = get_bits_count(&s->gb) - 32;
version = get_bits(&s->gb, 4) + 1;
hdr_size = get_bits(&s->gb, 8) + 1;
frame_size = get_bits_long(&s->gb, get_bits(&s->gb, 5) + 1) + 1;
s->xll_channels =
s->xll_residual_channels = 0;
s->xll_nch_sets = get_bits(&s->gb, 4) + 1;
s->xll_segments = 1 << get_bits(&s->gb, 4);
s->xll_log_smpl_in_seg = get_bits(&s->gb, 4);
s->xll_smpl_in_seg = 1 << s->xll_log_smpl_in_seg;
s->xll_bits4seg_size = get_bits(&s->gb, 5) + 1;
s->xll_banddata_crc = get_bits(&s->gb, 2);
s->xll_scalable_lsb = get_bits1(&s->gb);
s->xll_bits4ch_mask = get_bits(&s->gb, 5) + 1;
if (s->xll_scalable_lsb) {
s->xll_fixed_lsb_width = get_bits(&s->gb, 4);
if (s->xll_fixed_lsb_width)
av_log(s->avctx, AV_LOG_WARNING,
"XLL: fixed lsb width = %d, non-zero not supported.\n",
s->xll_fixed_lsb_width);
}
/* skip to the end of the common header */
i = get_bits_count(&s->gb);
if (hdr_pos + hdr_size * 8 > i)
skip_bits_long(&s->gb, hdr_pos + hdr_size * 8 - i);
for (chset_index = 0; chset_index < s->xll_nch_sets; chset_index++) {
XllChSetSubHeader *chset = &s->xll_chsets[chset_index];
hdr_pos = get_bits_count(&s->gb);
hdr_size = get_bits(&s->gb, 10) + 1;
chset->channels = get_bits(&s->gb, 4) + 1;
chset->residual_encode = get_bits(&s->gb, chset->channels);
chset->bit_resolution = get_bits(&s->gb, 5) + 1;
chset->bit_width = get_bits(&s->gb, 5) + 1;
chset->sampling_frequency = ff_dca_sampling_freqs[get_bits(&s->gb, 4)];
chset->samp_freq_interp = get_bits(&s->gb, 2);
chset->replacement_set = get_bits(&s->gb, 2);
if (chset->replacement_set)
chset->active_replace_set = get_bits(&s->gb, 1);
if (s->one2one_map_chtospkr) {
chset->primary_ch_set = get_bits(&s->gb, 1);
chset->downmix_coeff_code_embedded = get_bits(&s->gb, 1);
if (chset->downmix_coeff_code_embedded) {
chset->downmix_embedded = get_bits(&s->gb, 1);
if (chset->primary_ch_set) {
chset->downmix_type = get_bits(&s->gb, 3);
if (chset->downmix_type > 6) {
av_log(s->avctx, AV_LOG_ERROR,
"XLL: Invalid channel set downmix type\n");
return AVERROR_INVALIDDATA;
}
}
}
chset->hier_chset = get_bits(&s->gb, 1);
if (chset->downmix_coeff_code_embedded) {
/* nDownmixCoeffs is specified as N * M. For a primary
* channel set, it appears that N = number of
* channels, and M is the number of downmix channels.
*
* For a non-primary channel set, N is specified as
* number of channels + 1, and M is derived from the
* channel set hierarchy, and at least in simple cases
* M is the number of channels in preceding channel
* sets. */
if (chset->primary_ch_set) {
static const char dmix_table[7] = { 1, 2, 2, 3, 3, 4, 4 };
chset->downmix_ncoeffs = chset->channels * dmix_table[chset->downmix_type];
} else
chset->downmix_ncoeffs = (chset->channels + 1) * s->xll_channels;
if (chset->downmix_ncoeffs > DCA_XLL_DMIX_NCOEFFS_MAX) {
avpriv_request_sample(s->avctx,
"XLL: More than %d downmix coefficients",
DCA_XLL_DMIX_NCOEFFS_MAX);
return AVERROR_PATCHWELCOME;
} else if (chset->primary_ch_set) {
for (i = 0; i < chset->downmix_ncoeffs; i++)
if ((chset->downmix_coeffs[i] = dca_get_dmix_coeff(s)) == -1)
return AVERROR_INVALIDDATA;
} else {
unsigned c, r;
for (c = 0, i = 0; c < s->xll_channels; c++, i += chset->channels + 1) {
if ((chset->downmix_coeffs[i] = dca_get_inv_dmix_coeff(s)) == -1)
return AVERROR_INVALIDDATA;
for (r = 1; r <= chset->channels; r++) {
int32_t coeff = dca_get_dmix_coeff(s);
if (coeff == -1)
return AVERROR_INVALIDDATA;
chset->downmix_coeffs[i + r] =
(chset->downmix_coeffs[i] * (int64_t) coeff + (1 << 15)) >> 16;
}
}
}
}
chset->ch_mask_enabled = get_bits(&s->gb, 1);
if (chset->ch_mask_enabled)
chset->ch_mask = get_bits(&s->gb, s->xll_bits4ch_mask);
else
/* Skip speaker configuration bits */
skip_bits_long(&s->gb, 25 * chset->channels);
} else {
chset->primary_ch_set = 1;
chset->downmix_coeff_code_embedded = 0;
/* Spec: NumChHierChSet = 0, NumDwnMixCodeCoeffs = 0, whatever that means. */
chset->mapping_coeffs_present = get_bits(&s->gb, 1);
if (chset->mapping_coeffs_present) {
avpriv_report_missing_feature(s->avctx, "XLL: mapping coefficients");
return AVERROR_PATCHWELCOME;
}
}
if (chset->sampling_frequency > 96000)
chset->num_freq_bands = 2 * (1 + get_bits(&s->gb, 1));
else
chset->num_freq_bands = 1;
if (chset->num_freq_bands > 1) {
avpriv_report_missing_feature(s->avctx, "XLL: num_freq_bands > 1");
return AVERROR_PATCHWELCOME;
}
if (get_bits(&s->gb, 1)) { /* pw_ch_decor_enabled */
int bits = av_ceil_log2(chset->channels);
for (i = 0; i < chset->channels; i++) {
unsigned j = get_bits(&s->gb, bits);
if (j >= chset->channels) {
av_log(s->avctx, AV_LOG_ERROR,
"Original channel order value %u too large, only %d channels.\n",
j, chset->channels);
return AVERROR_INVALIDDATA;
}
chset->orig_chan_order[0][i] = j;
chset->orig_chan_order_inv[0][j] = i;
}
for (i = 0; i < chset->channels / 2; i++) {
if (get_bits(&s->gb, 1)) /* bChPFlag */
chset->pw_ch_pairs_coeffs[0][i] = get_bits_sm(&s->gb, 7);
else
chset->pw_ch_pairs_coeffs[0][i] = 0;
}
} else {
for (i = 0; i < chset->channels; i++)
chset->orig_chan_order[0][i] =
chset->orig_chan_order_inv[0][i] = i;
for (i = 0; i < chset->channels / 2; i++)
chset->pw_ch_pairs_coeffs[0][i] = 0;
}
/* Adaptive prediction order */
chset->adapt_order_max[0] = 0;
for (i = 0; i < chset->channels; i++) {
chset->adapt_order[0][i] = get_bits(&s->gb, 4);
if (chset->adapt_order_max[0] < chset->adapt_order[0][i])
chset->adapt_order_max[0] = chset->adapt_order[0][i];
}
/* Fixed prediction order, used in case the adaptive order
* above is zero */
for (i = 0; i < chset->channels; i++)
chset->fixed_order[0][i] =
chset->adapt_order[0][i] ? 0 : get_bits(&s->gb, 2);
for (i = 0; i < chset->channels; i++) {
unsigned j;
for (j = 0; j < chset->adapt_order[0][i]; j++)
chset->lpc_refl_coeffs_q_ind[0][i][j] = get_bits(&s->gb, 8);
}
if (s->xll_scalable_lsb) {
chset->lsb_fsize[0] = get_bits(&s->gb, s->xll_bits4seg_size);
for (i = 0; i < chset->channels; i++)
chset->scalable_lsbs[0][i] = get_bits(&s->gb, 4);
for (i = 0; i < chset->channels; i++)
chset->bit_width_adj_per_ch[0][i] = get_bits(&s->gb, 4);
} else {
memset(chset->scalable_lsbs[0], 0,
chset->channels * sizeof(chset->scalable_lsbs[0][0]));
memset(chset->bit_width_adj_per_ch[0], 0,
chset->channels * sizeof(chset->bit_width_adj_per_ch[0][0]));
}
s->xll_channels += chset->channels;
s->xll_residual_channels += chset->channels -
av_popcount(chset->residual_encode);
/* FIXME: Parse header data for extra frequency bands. */
/* Skip to end of channel set sub header. */
i = get_bits_count(&s->gb);
if (hdr_pos + 8 * hdr_size < i) {
av_log(s->avctx, AV_LOG_ERROR,
"chset header too large, %d bits, should be <= %d bits\n",
i - hdr_pos, 8 * hdr_size);
return AVERROR_INVALIDDATA;
}
if (hdr_pos + 8 * hdr_size > i)
skip_bits_long(&s->gb, hdr_pos + 8 * hdr_size - i);
}
return 0;
}
/* parse XLL navigation table */
int ff_dca_xll_decode_navi(DCAContext *s, int asset_end)
{
int nbands, band, chset, seg, data_start;
/* FIXME: Supports only a single frequency band */
nbands = 1;
for (band = 0; band < nbands; band++) {
s->xll_navi.band_size[band] = 0;
for (seg = 0; seg < s->xll_segments; seg++) {
/* Note: The spec, ETSI TS 102 114 V1.4.1 (2012-09), says
* we should read a base value for segment_size from the
* stream, before reading the sizes of the channel sets.
* But that's apparently incorrect. */
s->xll_navi.segment_size[band][seg] = 0;
for (chset = 0; chset < s->xll_nch_sets; chset++)
if (band < s->xll_chsets[chset].num_freq_bands) {
s->xll_navi.chset_size[band][seg][chset] =
get_bits(&s->gb, s->xll_bits4seg_size) + 1;
s->xll_navi.segment_size[band][seg] +=
s->xll_navi.chset_size[band][seg][chset];
}
s->xll_navi.band_size[band] += s->xll_navi.segment_size[band][seg];
}
}
/* Align to 8 bits and skip 16-bit CRC. */
skip_bits_long(&s->gb, 16 + ((-get_bits_count(&s->gb)) & 7));
data_start = get_bits_count(&s->gb);
if (data_start + 8 * s->xll_navi.band_size[0] > asset_end) {
av_log(s->avctx, AV_LOG_ERROR,
"XLL: Data in NAVI table exceeds containing asset\n"
"start: %d (bit), size %u (bytes), end %d (bit), error %u\n",
data_start, s->xll_navi.band_size[0], asset_end,
data_start + 8 * s->xll_navi.band_size[0] - asset_end);
return AVERROR_INVALIDDATA;
}
init_get_bits(&s->xll_navi.gb, s->gb.buffer + data_start / 8,
8 * s->xll_navi.band_size[0]);
return 0;
}
static void dca_xll_inv_adapt_pred(int *samples, int nsamples, unsigned order,
const int *prev, const uint8_t *q_ind)
{
static const uint16_t table[0x81] = {
0, 3070, 5110, 7140, 9156, 11154, 13132, 15085,
17010, 18904, 20764, 22588, 24373, 26117, 27818, 29474,
31085, 32648, 34164, 35631, 37049, 38418, 39738, 41008,
42230, 43404, 44530, 45609, 46642, 47630, 48575, 49477,
50337, 51157, 51937, 52681, 53387, 54059, 54697, 55302,
55876, 56421, 56937, 57426, 57888, 58326, 58741, 59132,
59502, 59852, 60182, 60494, 60789, 61066, 61328, 61576,
61809, 62029, 62236, 62431, 62615, 62788, 62951, 63105,
63250, 63386, 63514, 63635, 63749, 63855, 63956, 64051,
64140, 64224, 64302, 64376, 64446, 64512, 64573, 64631,
64686, 64737, 64785, 64830, 64873, 64913, 64950, 64986,
65019, 65050, 65079, 65107, 65133, 65157, 65180, 65202,
65222, 65241, 65259, 65275, 65291, 65306, 65320, 65333,
65345, 65357, 65368, 65378, 65387, 65396, 65405, 65413,
65420, 65427, 65434, 65440, 65446, 65451, 65456, 65461,
65466, 65470, 65474, 65478, 65481, 65485, 65488, 65491,
65535, /* Final value is for the -128 corner case, see below. */
};
int c[DCA_XLL_AORDER_MAX];
int64_t s;
unsigned i, j;
for (i = 0; i < order; i++) {
if (q_ind[i] & 1)
/* The index value 0xff corresponds to a lookup of entry 0x80 in
* the table, and no value is provided in the specification. */
c[i] = -table[(q_ind[i] >> 1) + 1];
else
c[i] = table[q_ind[i] >> 1];
}
/* The description in the spec is a bit convoluted. We can convert
* the reflected values to direct values in place, using a
* sequence of reflections operating on two values. */
for (i = 1; i < order; i++) {
/* i = 1: scale c[0]
* i = 2: reflect c[0] <-> c[1]
* i = 3: scale c[1], reflect c[0] <-> c[2]
* i = 4: reflect c[0] <-> c[3] reflect c[1] <-> c[2]
* ... */
if (i & 1)
c[i / 2] += ((int64_t) c[i] * c[i / 2] + 0x8000) >> 16;
for (j = 0; j < i / 2; j++) {
int r0 = c[j];
int r1 = c[i - j - 1];
c[j] += ((int64_t) c[i] * r1 + 0x8000) >> 16;
c[i - j - 1] += ((int64_t) c[i] * r0 + 0x8000) >> 16;
}
}
/* Apply predictor. */
/* NOTE: Processing samples in this order means that the
* predictor is applied to the newly reconstructed samples. */
if (prev) {
for (i = 0; i < order; i++) {
for (j = s = 0; j < i; j++)
s += (int64_t) c[j] * samples[i - 1 - j];
for (; j < order; j++)
s += (int64_t) c[j] * prev[DCA_XLL_AORDER_MAX + i - 1 - j];
samples[i] -= av_clip_intp2((s + 0x8000) >> 16, 24);
}
}
for (i = order; i < nsamples; i++) {
for (j = s = 0; j < order; j++)
s += (int64_t) c[j] * samples[i - 1 - j];
/* NOTE: Equations seem to imply addition, while the
* pseudocode seems to use subtraction.*/
samples[i] -= av_clip_intp2((s + 0x8000) >> 16, 24);
}
}
int ff_dca_xll_decode_audio(DCAContext *s, AVFrame *frame)
{
/* FIXME: Decodes only the first frequency band. */
int seg, chset_i;
/* Coding parameters for each channel set. */
struct coding_params {
int seg_type;
int rice_code_flag[16];
int pancAuxABIT[16];
int pancABIT0[16]; /* Not sure what this is */
int pancABIT[16]; /* Not sure what this is */
int nSamplPart0[16];
} param_state[16];
GetBitContext *gb = &s->xll_navi.gb;
int *history;
/* Layout: First the sample buffer for one segment per channel,
* followed by history buffers of DCA_XLL_AORDER_MAX samples for
* each channel. */
av_fast_malloc(&s->xll_sample_buf, &s->xll_sample_buf_size,
(s->xll_smpl_in_seg + DCA_XLL_AORDER_MAX) *
s->xll_channels * sizeof(*s->xll_sample_buf));
if (!s->xll_sample_buf)
return AVERROR(ENOMEM);
history = s->xll_sample_buf + s->xll_smpl_in_seg * s->xll_channels;
for (seg = 0; seg < s->xll_segments; seg++) {
unsigned in_channel;
for (chset_i = in_channel = 0; chset_i < s->xll_nch_sets; chset_i++) {
/* The spec isn't very explicit, but I think the NAVI sizes are in bytes. */
int end_pos = get_bits_count(gb) +
8 * s->xll_navi.chset_size[0][seg][chset_i];
int i, j;
struct coding_params *params = &param_state[chset_i];
/* I think this flag means that we should keep seg_type and
* other parameters from the previous segment. */
int use_seg_state_code_param;
XllChSetSubHeader *chset = &s->xll_chsets[chset_i];
if (in_channel >= s->avctx->channels)
/* FIXME: Could go directly to next segment */
goto next_chset;
if (s->avctx->sample_rate != chset->sampling_frequency) {
av_log(s->avctx, AV_LOG_WARNING,
"XLL: unexpected chset sample rate %d, expected %d\n",
chset->sampling_frequency, s->avctx->sample_rate);
goto next_chset;
}
if (seg != 0)
use_seg_state_code_param = get_bits(gb, 1);
else
use_seg_state_code_param = 0;
if (!use_seg_state_code_param) {
int num_param_sets, i;
unsigned bits4ABIT;
params->seg_type = get_bits(gb, 1);
num_param_sets = params->seg_type ? 1 : chset->channels;
if (chset->bit_width > 16) {
bits4ABIT = 5;
} else {
if (chset->bit_width > 8)
bits4ABIT = 4;
else
bits4ABIT = 3;
if (s->xll_nch_sets > 1)
bits4ABIT++;
}
for (i = 0; i < num_param_sets; i++) {
params->rice_code_flag[i] = get_bits(gb, 1);
if (!params->seg_type && params->rice_code_flag[i] && get_bits(gb, 1))
params->pancAuxABIT[i] = get_bits(gb, bits4ABIT) + 1;
else
params->pancAuxABIT[i] = 0;
}
for (i = 0; i < num_param_sets; i++) {
if (!seg) {
/* Parameters for part 1 */
params->pancABIT0[i] = get_bits(gb, bits4ABIT);
if (params->rice_code_flag[i] == 0 && params->pancABIT0[i] > 0)
/* For linear code */
params->pancABIT0[i]++;
/* NOTE: In the spec, not indexed by band??? */
if (params->seg_type == 0)
params->nSamplPart0[i] = chset->adapt_order[0][i];
else
params->nSamplPart0[i] = chset->adapt_order_max[0];
} else
params->nSamplPart0[i] = 0;
/* Parameters for part 2 */
params->pancABIT[i] = get_bits(gb, bits4ABIT);
if (params->rice_code_flag[i] == 0 && params->pancABIT[i] > 0)
/* For linear code */
params->pancABIT[i]++;
}
}
for (i = 0; i < chset->channels; i++) {
int param_index = params->seg_type ? 0 : i;
int part0 = params->nSamplPart0[param_index];
int bits = part0 ? params->pancABIT0[param_index] : 0;
int *sample_buf = s->xll_sample_buf +
(in_channel + i) * s->xll_smpl_in_seg;
if (!params->rice_code_flag[param_index]) {
/* Linear code */
if (bits)
for (j = 0; j < part0; j++)
sample_buf[j] = get_bits_sm(gb, bits);
else
memset(sample_buf, 0, part0 * sizeof(sample_buf[0]));
/* Second part */
bits = params->pancABIT[param_index];
if (bits)
for (j = part0; j < s->xll_smpl_in_seg; j++)
sample_buf[j] = get_bits_sm(gb, bits);
else
memset(sample_buf + part0, 0,
(s->xll_smpl_in_seg - part0) * sizeof(sample_buf[0]));
} else {
int aux_bits = params->pancAuxABIT[param_index];
for (j = 0; j < part0; j++) {
/* FIXME: Is this identical to Golomb code? */
int t = get_unary(gb, 1, 33) << bits;
/* FIXME: Could move this test outside of the loop, for efficiency. */
if (bits)
t |= get_bits(gb, bits);
sample_buf[j] = (t & 1) ? -(t >> 1) - 1 : (t >> 1);
}
/* Second part */
bits = params->pancABIT[param_index];
/* Follow the spec's suggestion of using the
* buffer also to store the hybrid-rice flags. */
memset(sample_buf + part0, 0,
(s->xll_smpl_in_seg - part0) * sizeof(sample_buf[0]));
if (aux_bits > 0) {
/* For hybrid rice encoding, some samples are linearly
* coded. According to the spec, "nBits4SamplLoci" bits
* are used for each index, but this value is not
* defined. I guess we should use log2(xll_smpl_in_seg)
* bits. */
int count = get_bits(gb, s->xll_log_smpl_in_seg);
av_log(s->avctx, AV_LOG_DEBUG, "aux count %d (bits %d)\n",
count, s->xll_log_smpl_in_seg);
for (j = 0; j < count; j++)
sample_buf[get_bits(gb, s->xll_log_smpl_in_seg)] = 1;
}
for (j = part0; j < s->xll_smpl_in_seg; j++) {
if (!sample_buf[j]) {
int t = get_unary(gb, 1, 33);
if (bits)
t = (t << bits) | get_bits(gb, bits);
sample_buf[j] = (t & 1) ? -(t >> 1) - 1 : (t >> 1);
} else
sample_buf[j] = get_bits_sm(gb, aux_bits);
}
}
}
for (i = 0; i < chset->channels; i++) {
unsigned adapt_order = chset->adapt_order[0][i];
int *sample_buf = s->xll_sample_buf +
(in_channel + i) * s->xll_smpl_in_seg;
int *prev = history + (in_channel + i) * DCA_XLL_AORDER_MAX;
if (!adapt_order) {
unsigned order;
for (order = chset->fixed_order[0][i]; order > 0; order--) {
unsigned j;
for (j = 1; j < s->xll_smpl_in_seg; j++)
sample_buf[j] += sample_buf[j - 1];
}
} else
/* Inverse adaptive prediction, in place. */
dca_xll_inv_adapt_pred(sample_buf, s->xll_smpl_in_seg,
adapt_order, seg ? prev : NULL,
chset->lpc_refl_coeffs_q_ind[0][i]);
memcpy(prev, sample_buf + s->xll_smpl_in_seg - DCA_XLL_AORDER_MAX,
DCA_XLL_AORDER_MAX * sizeof(*prev));
}
for (i = 1; i < chset->channels; i += 2) {
int coeff = chset->pw_ch_pairs_coeffs[0][i / 2];
if (coeff != 0) {
int *sample_buf = s->xll_sample_buf +
(in_channel + i) * s->xll_smpl_in_seg;
int *prev = sample_buf - s->xll_smpl_in_seg;
unsigned j;
for (j = 0; j < s->xll_smpl_in_seg; j++)
/* Shift is unspecified, but should apparently be 3. */
sample_buf[j] += ((int64_t) coeff * prev[j] + 4) >> 3;
}
}
if (s->xll_scalable_lsb) {
int lsb_start = end_pos - 8 * chset->lsb_fsize[0] -
8 * (s->xll_banddata_crc & 2);
int done;
i = get_bits_count(gb);
if (i > lsb_start) {
av_log(s->avctx, AV_LOG_ERROR,
"chset data lsb exceeds NAVI size, end_pos %d, lsb_start %d, pos %d\n",
end_pos, lsb_start, i);
return AVERROR_INVALIDDATA;
}
if (i < lsb_start)
skip_bits_long(gb, lsb_start - i);
for (i = done = 0; i < chset->channels; i++) {
int bits = chset->scalable_lsbs[0][i];
if (bits > 0) {
/* The channel reordering is conceptually done
* before adding the lsb:s, so we need to do
* the inverse permutation here. */
unsigned pi = chset->orig_chan_order_inv[0][i];
int *sample_buf = s->xll_sample_buf +
(in_channel + pi) * s->xll_smpl_in_seg;
int adj = chset->bit_width_adj_per_ch[0][i];
int msb_shift = bits;
unsigned j;
if (adj > 0)
msb_shift += adj - 1;
for (j = 0; j < s->xll_smpl_in_seg; j++)
sample_buf[j] = (sample_buf[j] << msb_shift) +
(get_bits(gb, bits) << adj);
done += bits * s->xll_smpl_in_seg;
}
}
if (done > 8 * chset->lsb_fsize[0]) {
av_log(s->avctx, AV_LOG_ERROR,
"chset lsb exceeds lsb_size\n");
return AVERROR_INVALIDDATA;
}
}
/* Store output. */
for (i = 0; i < chset->channels; i++) {
int *sample_buf = s->xll_sample_buf +
(in_channel + i) * s->xll_smpl_in_seg;
int shift = 1 - chset->bit_resolution;
int out_channel = chset->orig_chan_order[0][i];
float *out;
/* XLL uses the channel order C, L, R, and we want L,
* R, C. FIXME: Generalize. */
if (chset->ch_mask_enabled &&
(chset->ch_mask & 7) == 7 && out_channel < 3)
out_channel = out_channel ? out_channel - 1 : 2;
out_channel += in_channel;
if (out_channel >= s->avctx->channels)
continue;
out = (float *) frame->extended_data[out_channel];
out += seg * s->xll_smpl_in_seg;
/* NOTE: A one bit means residual encoding is *not* used. */
if ((chset->residual_encode >> i) & 1) {
/* Replace channel samples.
* FIXME: Most likely not the right thing to do. */
for (j = 0; j < s->xll_smpl_in_seg; j++)
out[j] = ldexpf(sample_buf[j], shift);
} else {
/* Add residual signal to core channel */
for (j = 0; j < s->xll_smpl_in_seg; j++)
out[j] += ldexpf(sample_buf[j], shift);
}
}
if (chset->downmix_coeff_code_embedded &&
!chset->primary_ch_set && chset->hier_chset) {
/* Undo hierarchical downmix of earlier channels. */
unsigned mix_channel;
for (mix_channel = 0; mix_channel < in_channel; mix_channel++) {
float *mix_buf;
const int *col;
float coeff;
unsigned row;
/* Similar channel reorder C, L, R vs L, R, C reorder. */
if (chset->ch_mask_enabled &&
(chset->ch_mask & 7) == 7 && mix_channel < 3)
mix_buf = (float *) frame->extended_data[mix_channel ? mix_channel - 1 : 2];
else
mix_buf = (float *) frame->extended_data[mix_channel];
mix_buf += seg * s->xll_smpl_in_seg;
col = &chset->downmix_coeffs[mix_channel * (chset->channels + 1)];
/* Scale */
coeff = ldexpf(col[0], -16);
for (j = 0; j < s->xll_smpl_in_seg; j++)
mix_buf[j] *= coeff;
for (row = 0;
row < chset->channels && in_channel + row < s->avctx->channels;
row++)
if (col[row + 1]) {
const float *new_channel =
(const float *) frame->extended_data[in_channel + row];
new_channel += seg * s->xll_smpl_in_seg;
coeff = ldexpf(col[row + 1], -15);
for (j = 0; j < s->xll_smpl_in_seg; j++)
mix_buf[j] -= coeff * new_channel[j];
}
}
}
next_chset:
in_channel += chset->channels;
/* Skip to next channel set using the NAVI info. */
i = get_bits_count(gb);
if (i > end_pos) {
av_log(s->avctx, AV_LOG_ERROR,
"chset data exceeds NAVI size\n");
return AVERROR_INVALIDDATA;
}
if (i < end_pos)
skip_bits_long(gb, end_pos - i);
}
}
return 0;
}
......@@ -22,7 +22,6 @@
#include <stdint.h>
#include "libavutil/channel_layout.h"
#include "libavutil/mem.h"
#include "dca.h"
......@@ -7509,76 +7508,6 @@ DECLARE_ALIGNED(16, const float, ff_dca_lfe_fir_128)[256] = {
};
#undef SCALE
#define SCALE(c) ((float)(c) / (256.0f * 32768.0f * 8388608.0f))
DECLARE_ALIGNED(16, const float, ff_dca_lfe_xll_fir_64)[256] = {
SCALE( 6103), SCALE( 52170), SCALE(-558064), SCALE(1592440),
SCALE(6290049), SCALE(1502534), SCALE(-546669), SCALE( 53047),
SCALE( 1930), SCALE( 51089), SCALE(-568920), SCALE(1683709),
SCALE(6286575), SCALE(1414057), SCALE(-534782), SCALE( 53729),
SCALE( 2228), SCALE( 49794), SCALE(-579194), SCALE(1776276),
SCALE(6279634), SCALE(1327070), SCALE(-522445), SCALE( 54228),
SCALE( 2552), SCALE( 48275), SCALE(-588839), SCALE(1870070),
SCALE(6269231), SCALE(1241632), SCALE(-509702), SCALE( 54550),
SCALE( 2904), SCALE( 46523), SCALE(-597808), SCALE(1965017),
SCALE(6255380), SCALE(1157798), SCALE(-496595), SCALE( 54708),
SCALE( 3287), SCALE( 44529), SCALE(-606054), SCALE(2061044),
SCALE(6238099), SCALE(1075621), SCALE(-483164), SCALE( 54710),
SCALE( 3704), SCALE( 42282), SCALE(-613529), SCALE(2158071),
SCALE(6217408), SCALE( 995149), SCALE(-469451), SCALE( 54566),
SCALE( 4152), SCALE( 39774), SCALE(-620186), SCALE(2256019),
SCALE(6193332), SCALE( 916430), SCALE(-455494), SCALE( 54285),
SCALE( 4631), SCALE( 36995), SCALE(-625976), SCALE(2354805),
SCALE(6165900), SCALE( 839507), SCALE(-441330), SCALE( 53876),
SCALE( 5139), SCALE( 33937), SCALE(-630850), SCALE(2454343),
SCALE(6135146), SCALE( 764419), SCALE(-426998), SCALE( 53348),
SCALE( 5682), SCALE( 30591), SCALE(-634759), SCALE(2554547),
SCALE(6101107), SCALE( 691203), SCALE(-412531), SCALE( 52711),
SCALE( 6264), SCALE( 26948), SCALE(-637655), SCALE(2655326),
SCALE(6063824), SCALE( 619894), SCALE(-397966), SCALE( 51972),
SCALE( 6886), SCALE( 23001), SCALE(-639488), SCALE(2756591),
SCALE(6023343), SCALE( 550521), SCALE(-383335), SCALE( 51140),
SCALE( 7531), SCALE( 18741), SCALE(-640210), SCALE(2858248),
SCALE(5979711), SCALE( 483113), SCALE(-368671), SCALE( 50224),
SCALE( 8230), SCALE( 14162), SCALE(-639772), SCALE(2960201),
SCALE(5932981), SCALE( 417692), SCALE(-354003), SCALE( 49231),
SCALE( 8959), SCALE( 9257), SCALE(-638125), SCALE(3062355),
SCALE(5883210), SCALE( 354281), SCALE(-339362), SCALE( 48168),
SCALE( 9727), SCALE( 4018), SCALE(-635222), SCALE(3164612),
SCALE(5830457), SCALE( 292897), SCALE(-324777), SCALE( 47044),
SCALE( 10535), SCALE( -1558), SCALE(-631014), SCALE(3266872),
SCALE(5774785), SCALE( 233555), SCALE(-310273), SCALE( 45866),
SCALE( 11381), SCALE( -7480), SCALE(-625455), SCALE(3369035),
SCALE(5716260), SCALE( 176267), SCALE(-295877), SCALE( 44640),
SCALE( 12267), SCALE( -13750), SCALE(-618499), SCALE(3471000),
SCALE(5654952), SCALE( 121042), SCALE(-281613), SCALE( 43373),
SCALE( 13190), SCALE( -20372), SCALE(-610098), SCALE(3572664),
SCALE(5590933), SCALE( 67886), SCALE(-267505), SCALE( 42072),
SCALE( 14152), SCALE( -27352), SCALE(-600209), SCALE(3673924),
SCALE(5524280), SCALE( 16800), SCALE(-253574), SCALE( 40743),
SCALE( 15153), SCALE( -34691), SCALE(-588788), SCALE(3774676),
SCALE(5455069), SCALE( -32214), SCALE(-239840), SCALE( 39391),
SCALE( 16192), SCALE( -42390), SCALE(-575791), SCALE(3874816),
SCALE(5383383), SCALE( -79159), SCALE(-226323), SCALE( 38022),
SCALE( 17267), SCALE( -50453), SCALE(-561178), SCALE(3974239),
SCALE(5309305), SCALE(-124041), SCALE(-213041), SCALE( 36642),
SCALE( 18377), SCALE( -58879), SCALE(-544906), SCALE(4072841),
SCALE(5232922), SCALE(-166869), SCALE(-200010), SCALE( 35256),
SCALE( 19525), SCALE( -67667), SCALE(-526937), SCALE(4170517),
SCALE(5154321), SCALE(-207653), SCALE(-187246), SCALE( 33866),
SCALE( 20704), SCALE( -76817), SCALE(-507233), SCALE(4267162),
SCALE(5073593), SCALE(-246406), SCALE(-174764), SCALE( 32480),
SCALE( 21915), SCALE( -86327), SCALE(-485757), SCALE(4362672),
SCALE(4990831), SCALE(-283146), SCALE(-162575), SCALE( 31101),
SCALE( 23157), SCALE( -96193), SCALE(-462476), SCALE(4456942),
SCALE(4906129), SCALE(-317890), SCALE(-150692), SCALE( 29732),
SCALE( 24426), SCALE(-106412), SCALE(-437356), SCALE(4549871),
SCALE(4819584), SCALE(-350658), SCALE(-139125), SCALE( 28376),
SCALE( 25721), SCALE(-116977), SCALE(-410365), SCALE(4641355),
SCALE(4731293), SCALE(-381475), SCALE(-127884), SCALE( 27038),
};
#undef SCALE
DECLARE_ALIGNED(16, const float, ff_dca_fir_64bands)[1024] = {
/* Bank 0 */
-7.1279389866041690e-8, -7.0950903150874990e-8,
......@@ -8178,220 +8107,11 @@ const uint32_t ff_dca_inv_dmixtable[FF_DCA_INV_DMIXTABLE_SIZE] = {
65536,
};
const float ff_dca_default_coeffs[10][6][2] = {
{ { 0.707107, 0.707107 }, { 0.000000, 0.000000 }, }, // A [LFE]
{ { 1.000000, 0.000000 }, { 0.000000, 1.000000 }, { 0.000000, 0.000000 }, }, // A + B (dual mono) [LFE]
{ { 1.000000, 0.000000 }, { 0.000000, 1.000000 }, { 0.000000, 0.000000 }, }, // L + R (stereo) [LFE]
{ { 1.000000, 0.000000 }, { 0.000000, 1.000000 }, { 0.000000, 0.000000 }, }, // (L+R) + (L-R) (sum-difference) [LFE]
{ { 1.000000, 0.000000 }, { 0.000000, 1.000000 }, { 0.000000, 0.000000 }, }, // LT + RT (left and right total) [LFE]
{ { 0.501187, 0.501187 }, { 0.707107, 0.000000 }, { 0.000000, 0.707107 }, { 0.000000, 0.000000 }, }, // C + L + R [LFE]
{ { 0.707107, 0.000000 }, { 0.000000, 0.707107 }, { 0.501187, 0.501187 }, { 0.000000, 0.000000 }, }, // L + R + S [LFE]
{ { 0.501187, 0.501187 }, { 0.707107, 0.000000 }, { 0.000000, 0.707107 }, { 0.501187, 0.501187 }, { 0.000000, 0.000000 }, }, // C + L + R + S [LFE]
{ { 0.707107, 0.000000 }, { 0.000000, 0.707107 }, { 0.501187, 0.000000 }, { 0.000000, 0.501187 }, { 0.000000, 0.000000 }, }, // L + R + SL + SR [LFE]
{ { 0.501187, 0.501187 }, { 0.707107, 0.000000 }, { 0.000000, 0.707107 }, { 0.501187, 0.000000 }, { 0.000000, 0.501187 }, { 0.000000, 0.000000 }, }, // C + L + R + SL + SR [LFE]
};
const int32_t ff_dca_sampling_freqs[16] = {
8000, 16000, 32000, 64000, 128000, 22050, 44100, 88200,
176400, 352800, 12000, 24000, 48000, 96000, 192000, 384000,
};
/* downmix coeffs
*
* TABLE 9
* ______________________________________
* Down-mix coefficients for 8-channel source
* audio (5 + 3 format)
* lt
* cen- rt lt ctr rt
* lt ter ctr center
* rt srd srd srd
* ______________________________________
* 1 0.71 0.74 1.0 0.71 0.71 0.58 0.58 0.58
* 2 left 1.0 0.89 0.71 0.46 0.71 0.50
* rt 0.45 0.71 0.89 1.0 0.50 0.71
* 3 lt 1.0 0.89 0.71 0.45
* rt 0.45 0.71 0.89 1.0
* srd 0.71 0.71 0.71
* 4 lt 1.0 0.89 0.71 0.45
* rt 0.45 0.71 0.89 1.0
* lt srd 1.0 0.71
* rt srd 0.71 0.71
* 4 lt 1.0 0.5
* ctr 0.87 1.0 0.87
* rt 0.5 1.0
* srd 0.71 0.71 0.71
* 5 lt 1.0 0.5
* ctr 0.87 1.0 0.87
* rt 0.5 1.0
* lt srd 1.0 0.71
* rt srd 0.71 1.0
* 6 lt 1.0 0.5
* lt ctr 0.87 0.71
* rt ctr 0.71 0.87
* rt 0.5 1.0
* lt srd 1.0 0.71
* rt srd 0.71 1.0
* 6 lt 1.0 0.5
* ctr 0.86 1.0 0.86
* rt 0.5 1.0
* lt srd 1.0
* ctr srd 1.0
* rt srd 1.0
* 7 lt 1.0
* lt ctr 1.0
* ctr 1.0
* rt ctr 1.0
* rt 1.0
* lt srd 1.0 0.71
* rt srd 0.71 1.0
* 7 lt 1.0 0.5
* lt ctr 0.87 0.71
* rt ctr 0.71 0.87
* rt 0.5 1.0
* lt srd 1.0
* ctr srd 1.0
* rt srd 1.0
* 8 lt 1.0 0.5
* lt ctr 0.87 0.71
* rt ctr 0.71 0.87
* rt 0.5 1.0
* lt 1 srd 0.87 0.35
* lt 2 srd 0.5 0.61
* rt 2 srd 0.61 0.50
* rt 2 srd 0.35 0.87
*
* Generation of Lt Rt
*
* In the case when the playback system has analog or digital surround
* multi-channel capability, a down matrix from 5, 4, or 3 channel to
* Lt Rt may be desirable. In the case when the number of decoded audio
* channels exceeds 5, 4 or 3 respectively a first stage down mix to 5,
* 4 or 3 chs should be used as described above.
*
* The down matrixing equations for 5-channel source audio to a
* two-channel Lt Rt playback system are given by:
*
* Left = left + 0.7 * center - 0.7 * (lt surround + rt surround)
*
* Right = right + 0.7 * center + 0.7 * (lt surround + rt surround)
*
* Embedded mixing to 2-channel
*
* One concern arising from the proliferation of multi-channel audio
* systems is that most home systems presently have only two channel
* playback capability. To accommodate this a fixed 2-channel down
* matrix processes is commonly used following the multi-channel
* decoding stage. However, for music only applications the image
* quality etc. of the down matrixed signal may not match that of an
* equivalent stereo recording found on CD.
*
* The concept of embedded mixing is to allow the producer to
* dynamically specify the matrixing coefficients within the audio
* frame itself. In this way the stereo down mix at the decoder may be
* better matched to a 2-channel playback environment.
*
* CHS*2, 7-bit down mix indexes (MCOEFFS) are transmitted along with
* the multi-channel audio once in every frame. The indexes are
* converted to attenuation factors using a 7 bit LUT. The 2-ch down
* mix equations are as follows,
*
* Left Ch = sum (MCOEFF[n] * Ch[n]) for n=1, CHS
*
* Right Ch = sum (MCOEFF[n + CHS] * Ch[n]) for n=1, CHS
*
* where Ch(n) represents the subband samples in the (n)th audio channel.
*/
const uint32_t ff_dca_map_xxch_to_native[28] = {
AV_CH_FRONT_CENTER,
AV_CH_FRONT_LEFT,
AV_CH_FRONT_RIGHT,
AV_CH_SIDE_LEFT,
AV_CH_SIDE_RIGHT,
AV_CH_LOW_FREQUENCY,
AV_CH_BACK_CENTER,
AV_CH_BACK_LEFT,
AV_CH_BACK_RIGHT,
AV_CH_SIDE_LEFT, /* side surround left -- dup sur side L */
AV_CH_SIDE_RIGHT, /* side surround right -- dup sur side R */
AV_CH_FRONT_LEFT_OF_CENTER,
AV_CH_FRONT_RIGHT_OF_CENTER,
AV_CH_TOP_FRONT_LEFT,
AV_CH_TOP_FRONT_CENTER,
AV_CH_TOP_FRONT_RIGHT,
AV_CH_LOW_FREQUENCY, /* lfe2 -- duplicate lfe1 position */
AV_CH_FRONT_LEFT_OF_CENTER, /* side front left -- dup front cntr L */
AV_CH_FRONT_RIGHT_OF_CENTER,/* side front right -- dup front cntr R */
AV_CH_TOP_CENTER, /* overhead */
AV_CH_TOP_FRONT_LEFT, /* side high left -- dup */
AV_CH_TOP_FRONT_RIGHT, /* side high right -- dup */
AV_CH_TOP_BACK_CENTER,
AV_CH_TOP_BACK_LEFT,
AV_CH_TOP_BACK_RIGHT,
AV_CH_BACK_CENTER, /* rear low center -- dup */
AV_CH_BACK_LEFT, /* rear low left -- dup */
AV_CH_BACK_RIGHT /* read low right -- dup */
};
/* -1 are reserved or unknown */
const int ff_dca_ext_audio_descr_mask[8] = {
DCA_EXT_XCH,
-1,
DCA_EXT_X96,
DCA_EXT_XCH | DCA_EXT_X96,
-1,
-1,
DCA_EXT_XXCH,
-1,
};
/* Tables for mapping dts channel configurations to libavcodec multichannel api.
* Some compromises have been made for special configurations. Most configurations
* are never used so complete accuracy is not needed.
*
* L = left, R = right, C = center, S = surround, F = front, R = rear, T = total, OV = overhead.
* S -> side, when both rear and back are configured move one of them to the side channel
* OV -> center back
* All 2 channel configurations -> AV_CH_LAYOUT_STEREO
*/
const uint64_t ff_dca_core_channel_layout[16] = {
AV_CH_FRONT_CENTER, ///< 1, A
AV_CH_LAYOUT_STEREO, ///< 2, A + B (dual mono)
AV_CH_LAYOUT_STEREO, ///< 2, L + R (stereo)
AV_CH_LAYOUT_STEREO, ///< 2, (L + R) + (L - R) (sum-difference)
AV_CH_LAYOUT_STEREO, ///< 2, LT + RT (left and right total)
AV_CH_LAYOUT_STEREO | AV_CH_FRONT_CENTER, ///< 3, C + L + R
AV_CH_LAYOUT_STEREO | AV_CH_BACK_CENTER, ///< 3, L + R + S
AV_CH_LAYOUT_STEREO | AV_CH_FRONT_CENTER | AV_CH_BACK_CENTER, ///< 4, C + L + R + S
AV_CH_LAYOUT_STEREO | AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT, ///< 4, L + R + SL + SR
AV_CH_LAYOUT_STEREO | AV_CH_FRONT_CENTER | AV_CH_SIDE_LEFT |
AV_CH_SIDE_RIGHT, ///< 5, C + L + R + SL + SR
AV_CH_LAYOUT_STEREO | AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT |
AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER, ///< 6, CL + CR + L + R + SL + SR
AV_CH_LAYOUT_STEREO | AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT |
AV_CH_FRONT_CENTER | AV_CH_BACK_CENTER, ///< 6, C + L + R + LR + RR + OV
AV_CH_FRONT_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER |
AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_BACK_CENTER |
AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT, ///< 6, CF + CR + LF + RF + LR + RR
AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_CENTER |
AV_CH_FRONT_RIGHT_OF_CENTER | AV_CH_LAYOUT_STEREO |
AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT, ///< 7, CL + C + CR + L + R + SL + SR
AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER |
AV_CH_LAYOUT_STEREO | AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT |
AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT, ///< 8, CL + CR + L + R + SL1 + SL2 + SR1 + SR2
AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_CENTER |
AV_CH_FRONT_RIGHT_OF_CENTER | AV_CH_LAYOUT_STEREO |
AV_CH_SIDE_LEFT | AV_CH_BACK_CENTER | AV_CH_SIDE_RIGHT, ///< 8, CL + C + CR + L + R + SL + S + SR
};
const int8_t ff_dca_lfe_index[16] = {
1, 2, 2, 2, 2, 3, 2, 3, 2, 3, 2, 3, 1, 3, 2, 3
};
......@@ -8415,25 +8135,6 @@ const int8_t ff_dca_channel_reorder_lfe[16][9] = {
{ 4, 2, 5, 0, 1, 6, 8, 7, -1 },
};
const int8_t ff_dca_channel_reorder_lfe_xch[16][9] = {
{ 0, 2, -1, -1, -1, -1, -1, -1, -1 },
{ 0, 1, 3, -1, -1, -1, -1, -1, -1 },
{ 0, 1, 3, -1, -1, -1, -1, -1, -1 },
{ 0, 1, 3, -1, -1, -1, -1, -1, -1 },
{ 0, 1, 3, -1, -1, -1, -1, -1, -1 },
{ 2, 0, 1, 4, -1, -1, -1, -1, -1 },
{ 0, 1, 3, 4, -1, -1, -1, -1, -1 },
{ 2, 0, 1, 4, 5, -1, -1, -1, -1 },
{ 0, 1, 4, 5, 3, -1, -1, -1, -1 },
{ 2, 0, 1, 5, 6, 4, -1, -1, -1 },
{ 3, 4, 0, 1, 6, 7, 5, -1, -1 },
{ 2, 0, 1, 4, 5, 6, 7, -1, -1 },
{ 0, 6, 4, 5, 2, 3, 7, -1, -1 },
{ 4, 2, 5, 0, 1, 7, 8, 6, -1 },
{ 5, 6, 0, 1, 8, 3, 9, 4, 7 },
{ 4, 2, 5, 0, 1, 6, 9, 8, 7 },
};
const int8_t ff_dca_channel_reorder_nolfe[16][9] = {
{ 0, -1, -1, -1, -1, -1, -1, -1, -1 },
{ 0, 1, -1, -1, -1, -1, -1, -1, -1 },
......@@ -8453,25 +8154,6 @@ const int8_t ff_dca_channel_reorder_nolfe[16][9] = {
{ 3, 2, 4, 0, 1, 5, 7, 6, -1 },
};
const int8_t ff_dca_channel_reorder_nolfe_xch[16][9] = {
{ 0, 1, -1, -1, -1, -1, -1, -1, -1 },
{ 0, 1, 2, -1, -1, -1, -1, -1, -1 },
{ 0, 1, 2, -1, -1, -1, -1, -1, -1 },
{ 0, 1, 2, -1, -1, -1, -1, -1, -1 },
{ 0, 1, 2, -1, -1, -1, -1, -1, -1 },
{ 2, 0, 1, 3, -1, -1, -1, -1, -1 },
{ 0, 1, 2, 3, -1, -1, -1, -1, -1 },
{ 2, 0, 1, 3, 4, -1, -1, -1, -1 },
{ 0, 1, 3, 4, 2, -1, -1, -1, -1 },
{ 2, 0, 1, 4, 5, 3, -1, -1, -1 },
{ 2, 3, 0, 1, 5, 6, 4, -1, -1 },
{ 2, 0, 1, 3, 4, 5, 6, -1, -1 },
{ 0, 5, 3, 4, 1, 2, 6, -1, -1 },
{ 3, 2, 4, 0, 1, 6, 7, 5, -1 },
{ 4, 5, 0, 1, 7, 2, 8, 3, 6 },
{ 3, 2, 4, 0, 1, 5, 8, 7, 6 },
};
const uint16_t ff_dca_vlc_offs[63] = {
0, 512, 640, 768, 1282, 1794, 2436, 3080, 3770, 4454, 5364,
5372, 5380, 5388, 5392, 5396, 5412, 5420, 5428, 5460, 5492, 5508,
......
......@@ -45,7 +45,6 @@ extern const float ff_dca_fir_32bands_nonperfect[512];
extern const float ff_dca_lfe_fir_64[256];
extern const float ff_dca_lfe_fir_128[256];
extern const float ff_dca_lfe_xll_fir_64[256];
extern const float ff_dca_fir_64bands[1024];
#define FF_DCA_DMIXTABLE_SIZE 242
......@@ -54,21 +53,12 @@ extern const float ff_dca_fir_64bands[1024];
extern const uint16_t ff_dca_dmixtable[FF_DCA_DMIXTABLE_SIZE];
extern const uint32_t ff_dca_inv_dmixtable[FF_DCA_INV_DMIXTABLE_SIZE];
extern const float ff_dca_default_coeffs[10][6][2];
extern const uint32_t ff_dca_map_xxch_to_native[28];
extern const int ff_dca_ext_audio_descr_mask[8];
extern const uint64_t ff_dca_core_channel_layout[16];
extern const int32_t ff_dca_sampling_freqs[16];
extern const int8_t ff_dca_lfe_index[16];
extern const int8_t ff_dca_channel_reorder_lfe[16][9];
extern const int8_t ff_dca_channel_reorder_lfe_xch[16][9];
extern const int8_t ff_dca_channel_reorder_nolfe[16][9];
extern const int8_t ff_dca_channel_reorder_nolfe_xch[16][9];
extern const uint16_t ff_dca_vlc_offs[63];
......
/*
* DCA compatible decoder
* Copyright (C) 2004 Gildas Bazin
* Copyright (C) 2004 Benjamin Zores
* Copyright (C) 2006 Benjamin Larsson
* Copyright (C) 2007 Konstantin Shishkov
* Copyright (C) 2012 Paul B Mahol
* Copyright (C) 2014 Niels Möller
*
* 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 <math.h>
#include <stddef.h>
#include <stdio.h>
#include "libavutil/attributes.h"
#include "libavutil/channel_layout.h"
#include "libavutil/common.h"
#include "libavutil/float_dsp.h"
#include "libavutil/internal.h"
#include "libavutil/intreadwrite.h"
#include "libavutil/mathematics.h"
#include "libavutil/opt.h"
#include "libavutil/samplefmt.h"
#include "avcodec.h"
#include "dca.h"
#include "dca_syncwords.h"
#include "dcadata.h"
#include "dcadsp.h"
#include "dcahuff.h"
#include "fft.h"
#include "fmtconvert.h"
#include "get_bits.h"
#include "internal.h"
#include "mathops.h"
#include "profiles.h"
#include "synth_filter.h"
#if ARCH_ARM
# include "arm/dca.h"
#endif
enum DCAMode {
DCA_MONO = 0,
DCA_CHANNEL,
DCA_STEREO,
DCA_STEREO_SUMDIFF,
DCA_STEREO_TOTAL,
DCA_3F,
DCA_2F1R,
DCA_3F1R,
DCA_2F2R,
DCA_3F2R,
DCA_4F2R
};
enum DCAXxchSpeakerMask {
DCA_XXCH_FRONT_CENTER = 0x0000001,
DCA_XXCH_FRONT_LEFT = 0x0000002,
DCA_XXCH_FRONT_RIGHT = 0x0000004,
DCA_XXCH_SIDE_REAR_LEFT = 0x0000008,
DCA_XXCH_SIDE_REAR_RIGHT = 0x0000010,
DCA_XXCH_LFE1 = 0x0000020,
DCA_XXCH_REAR_CENTER = 0x0000040,
DCA_XXCH_SURROUND_REAR_LEFT = 0x0000080,
DCA_XXCH_SURROUND_REAR_RIGHT = 0x0000100,
DCA_XXCH_SIDE_SURROUND_LEFT = 0x0000200,
DCA_XXCH_SIDE_SURROUND_RIGHT = 0x0000400,
DCA_XXCH_FRONT_CENTER_LEFT = 0x0000800,
DCA_XXCH_FRONT_CENTER_RIGHT = 0x0001000,
DCA_XXCH_FRONT_HIGH_LEFT = 0x0002000,
DCA_XXCH_FRONT_HIGH_CENTER = 0x0004000,
DCA_XXCH_FRONT_HIGH_RIGHT = 0x0008000,
DCA_XXCH_LFE2 = 0x0010000,
DCA_XXCH_SIDE_FRONT_LEFT = 0x0020000,
DCA_XXCH_SIDE_FRONT_RIGHT = 0x0040000,
DCA_XXCH_OVERHEAD = 0x0080000,
DCA_XXCH_SIDE_HIGH_LEFT = 0x0100000,
DCA_XXCH_SIDE_HIGH_RIGHT = 0x0200000,
DCA_XXCH_REAR_HIGH_CENTER = 0x0400000,
DCA_XXCH_REAR_HIGH_LEFT = 0x0800000,
DCA_XXCH_REAR_HIGH_RIGHT = 0x1000000,
DCA_XXCH_REAR_LOW_CENTER = 0x2000000,
DCA_XXCH_REAR_LOW_LEFT = 0x4000000,
DCA_XXCH_REAR_LOW_RIGHT = 0x8000000,
};
#define DCA_DOLBY 101 /* FIXME */
#define DCA_CHANNEL_BITS 6
#define DCA_CHANNEL_MASK 0x3F
#define DCA_LFE 0x80
#define HEADER_SIZE 14
#define DCA_NSYNCAUX 0x9A1105A0
/** Bit allocation */
typedef struct BitAlloc {
int offset; ///< code values offset
int maxbits[8]; ///< max bits in VLC
int wrap; ///< wrap for get_vlc2()
VLC vlc[8]; ///< actual codes
} BitAlloc;
static BitAlloc dca_bitalloc_index; ///< indexes for samples VLC select
static BitAlloc dca_tmode; ///< transition mode VLCs
static BitAlloc dca_scalefactor; ///< scalefactor VLCs
static BitAlloc dca_smpl_bitalloc[11]; ///< samples VLCs
static av_always_inline int get_bitalloc(GetBitContext *gb, BitAlloc *ba,
int idx)
{
return get_vlc2(gb, ba->vlc[idx].table, ba->vlc[idx].bits, ba->wrap) +
ba->offset;
}
static float dca_dmix_code(unsigned code);
static av_cold void dca_init_vlcs(void)
{
static int vlcs_initialized = 0;
int i, j, c = 14;
static VLC_TYPE dca_table[23622][2];
if (vlcs_initialized)
return;
dca_bitalloc_index.offset = 1;
dca_bitalloc_index.wrap = 2;
for (i = 0; i < 5; i++) {
dca_bitalloc_index.vlc[i].table = &dca_table[ff_dca_vlc_offs[i]];
dca_bitalloc_index.vlc[i].table_allocated = ff_dca_vlc_offs[i + 1] - ff_dca_vlc_offs[i];
init_vlc(&dca_bitalloc_index.vlc[i], bitalloc_12_vlc_bits[i], 12,
bitalloc_12_bits[i], 1, 1,
bitalloc_12_codes[i], 2, 2, INIT_VLC_USE_NEW_STATIC);
}
dca_scalefactor.offset = -64;
dca_scalefactor.wrap = 2;
for (i = 0; i < 5; i++) {
dca_scalefactor.vlc[i].table = &dca_table[ff_dca_vlc_offs[i + 5]];
dca_scalefactor.vlc[i].table_allocated = ff_dca_vlc_offs[i + 6] - ff_dca_vlc_offs[i + 5];
init_vlc(&dca_scalefactor.vlc[i], SCALES_VLC_BITS, 129,
scales_bits[i], 1, 1,
scales_codes[i], 2, 2, INIT_VLC_USE_NEW_STATIC);
}
dca_tmode.offset = 0;
dca_tmode.wrap = 1;
for (i = 0; i < 4; i++) {
dca_tmode.vlc[i].table = &dca_table[ff_dca_vlc_offs[i + 10]];
dca_tmode.vlc[i].table_allocated = ff_dca_vlc_offs[i + 11] - ff_dca_vlc_offs[i + 10];
init_vlc(&dca_tmode.vlc[i], tmode_vlc_bits[i], 4,
tmode_bits[i], 1, 1,
tmode_codes[i], 2, 2, INIT_VLC_USE_NEW_STATIC);
}
for (i = 0; i < 10; i++)
for (j = 0; j < 7; j++) {
if (!bitalloc_codes[i][j])
break;
dca_smpl_bitalloc[i + 1].offset = bitalloc_offsets[i];
dca_smpl_bitalloc[i + 1].wrap = 1 + (j > 4);
dca_smpl_bitalloc[i + 1].vlc[j].table = &dca_table[ff_dca_vlc_offs[c]];
dca_smpl_bitalloc[i + 1].vlc[j].table_allocated = ff_dca_vlc_offs[c + 1] - ff_dca_vlc_offs[c];
init_vlc(&dca_smpl_bitalloc[i + 1].vlc[j], bitalloc_maxbits[i][j],
bitalloc_sizes[i],
bitalloc_bits[i][j], 1, 1,
bitalloc_codes[i][j], 2, 2, INIT_VLC_USE_NEW_STATIC);
c++;
}
vlcs_initialized = 1;
}
static inline void get_array(GetBitContext *gb, int *dst, int len, int bits)
{
while (len--)
*dst++ = get_bits(gb, bits);
}
static inline int dca_xxch2index(DCAContext *s, int xxch_ch)
{
int i, base, mask;
/* locate channel set containing the channel */
for (i = -1, base = 0, mask = (s->xxch_core_spkmask & ~DCA_XXCH_LFE1);
i <= s->xxch_chset && !(mask & xxch_ch); mask = s->xxch_spk_masks[++i])
base += av_popcount(mask);
return base + av_popcount(mask & (xxch_ch - 1));
}
static int dca_parse_audio_coding_header(DCAContext *s, int base_channel,
int xxch)
{
int i, j;
static const uint8_t adj_table[4] = { 16, 18, 20, 23 };
static const int bitlen[11] = { 0, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3 };
static const int thr[11] = { 0, 1, 3, 3, 3, 3, 7, 7, 7, 7, 7 };
int hdr_pos = 0, hdr_size = 0;
float scale_factor;
int this_chans, acc_mask;
int embedded_downmix;
int nchans, mask[8];
int coeff, ichan;
/* xxch has arbitrary sized audio coding headers */
if (xxch) {
hdr_pos = get_bits_count(&s->gb);
hdr_size = get_bits(&s->gb, 7) + 1;
}
nchans = get_bits(&s->gb, 3) + 1;
if (xxch && nchans >= 3) {
av_log(s->avctx, AV_LOG_ERROR, "nchans %d is too large\n", nchans);
return AVERROR_INVALIDDATA;
} else if (nchans + base_channel > DCA_PRIM_CHANNELS_MAX) {
av_log(s->avctx, AV_LOG_ERROR, "channel sum %d + %d is too large\n", nchans, base_channel);
return AVERROR_INVALIDDATA;
}
s->audio_header.total_channels = nchans + base_channel;
s->audio_header.prim_channels = s->audio_header.total_channels;
/* obtain speaker layout mask & downmix coefficients for XXCH */
if (xxch) {
acc_mask = s->xxch_core_spkmask;
this_chans = get_bits(&s->gb, s->xxch_nbits_spk_mask - 6) << 6;
s->xxch_spk_masks[s->xxch_chset] = this_chans;
s->xxch_chset_nch[s->xxch_chset] = nchans;
for (i = 0; i <= s->xxch_chset; i++)
acc_mask |= s->xxch_spk_masks[i];
/* check for downmixing information */
if (get_bits1(&s->gb)) {
embedded_downmix = get_bits1(&s->gb);
coeff = get_bits(&s->gb, 6);
if (coeff<1 || coeff>61) {
av_log(s->avctx, AV_LOG_ERROR, "6bit coeff %d is out of range\n", coeff);
return AVERROR_INVALIDDATA;
}
scale_factor = -1.0f / dca_dmix_code((coeff<<2)-3);
s->xxch_dmix_sf[s->xxch_chset] = scale_factor;
for (i = base_channel; i < s->audio_header.prim_channels; i++) {
mask[i] = get_bits(&s->gb, s->xxch_nbits_spk_mask);
}
for (j = base_channel; j < s->audio_header.prim_channels; j++) {
memset(s->xxch_dmix_coeff[j], 0, sizeof(s->xxch_dmix_coeff[0]));
s->xxch_dmix_embedded |= (embedded_downmix << j);
for (i = 0; i < s->xxch_nbits_spk_mask; i++) {
if (mask[j] & (1 << i)) {
if ((1 << i) == DCA_XXCH_LFE1) {
av_log(s->avctx, AV_LOG_WARNING,
"DCA-XXCH: dmix to LFE1 not supported.\n");
continue;
}
coeff = get_bits(&s->gb, 7);
ichan = dca_xxch2index(s, 1 << i);
if ((coeff&63)<1 || (coeff&63)>61) {
av_log(s->avctx, AV_LOG_ERROR, "7bit coeff %d is out of range\n", coeff);
return AVERROR_INVALIDDATA;
}
s->xxch_dmix_coeff[j][ichan] = dca_dmix_code((coeff<<2)-3);
}
}
}
}
}
if (s->audio_header.prim_channels > DCA_PRIM_CHANNELS_MAX)
s->audio_header.prim_channels = DCA_PRIM_CHANNELS_MAX;
for (i = base_channel; i < s->audio_header.prim_channels; i++) {
s->audio_header.subband_activity[i] = get_bits(&s->gb, 5) + 2;
if (s->audio_header.subband_activity[i] > DCA_SUBBANDS)
s->audio_header.subband_activity[i] = DCA_SUBBANDS;
}
for (i = base_channel; i < s->audio_header.prim_channels; i++) {
s->audio_header.vq_start_subband[i] = get_bits(&s->gb, 5) + 1;
if (s->audio_header.vq_start_subband[i] > DCA_SUBBANDS)
s->audio_header.vq_start_subband[i] = DCA_SUBBANDS;
}
get_array(&s->gb, s->audio_header.joint_intensity + base_channel,
s->audio_header.prim_channels - base_channel, 3);
get_array(&s->gb, s->audio_header.transient_huffman + base_channel,
s->audio_header.prim_channels - base_channel, 2);
get_array(&s->gb, s->audio_header.scalefactor_huffman + base_channel,
s->audio_header.prim_channels - base_channel, 3);
get_array(&s->gb, s->audio_header.bitalloc_huffman + base_channel,
s->audio_header.prim_channels - base_channel, 3);
/* Get codebooks quantization indexes */
if (!base_channel)
memset(s->audio_header.quant_index_huffman, 0, sizeof(s->audio_header.quant_index_huffman));
for (j = 1; j < 11; j++)
for (i = base_channel; i < s->audio_header.prim_channels; i++)
s->audio_header.quant_index_huffman[i][j] = get_bits(&s->gb, bitlen[j]);
/* Get scale factor adjustment */
for (j = 0; j < 11; j++)
for (i = base_channel; i < s->audio_header.prim_channels; i++)
s->audio_header.scalefactor_adj[i][j] = 16;
for (j = 1; j < 11; j++)
for (i = base_channel; i < s->audio_header.prim_channels; i++)
if (s->audio_header.quant_index_huffman[i][j] < thr[j])
s->audio_header.scalefactor_adj[i][j] = adj_table[get_bits(&s->gb, 2)];
if (!xxch) {
if (s->crc_present) {
/* Audio header CRC check */
get_bits(&s->gb, 16);
}
} else {
/* Skip to the end of the header, also ignore CRC if present */
i = get_bits_count(&s->gb);
if (hdr_pos + 8 * hdr_size > i)
skip_bits_long(&s->gb, hdr_pos + 8 * hdr_size - i);
}
s->current_subframe = 0;
s->current_subsubframe = 0;
return 0;
}
static int dca_parse_frame_header(DCAContext *s)
{
init_get_bits(&s->gb, s->dca_buffer, s->dca_buffer_size * 8);
/* Sync code */
skip_bits_long(&s->gb, 32);
/* Frame header */
s->frame_type = get_bits(&s->gb, 1);
s->samples_deficit = get_bits(&s->gb, 5) + 1;
s->crc_present = get_bits(&s->gb, 1);
s->sample_blocks = get_bits(&s->gb, 7) + 1;
s->frame_size = get_bits(&s->gb, 14) + 1;
if (s->frame_size < 95)
return AVERROR_INVALIDDATA;
s->amode = get_bits(&s->gb, 6);
s->sample_rate = avpriv_dca_sample_rates[get_bits(&s->gb, 4)];
if (!s->sample_rate)
return AVERROR_INVALIDDATA;
s->bit_rate_index = get_bits(&s->gb, 5);
s->bit_rate = ff_dca_bit_rates[s->bit_rate_index];
if (!s->bit_rate)
return AVERROR_INVALIDDATA;
skip_bits1(&s->gb); // always 0 (reserved, cf. ETSI TS 102 114 V1.4.1)
s->dynrange = get_bits(&s->gb, 1);
s->timestamp = get_bits(&s->gb, 1);
s->aux_data = get_bits(&s->gb, 1);
s->hdcd = get_bits(&s->gb, 1);
s->ext_descr = get_bits(&s->gb, 3);
s->ext_coding = get_bits(&s->gb, 1);
s->aspf = get_bits(&s->gb, 1);
s->lfe = get_bits(&s->gb, 2);
s->predictor_history = get_bits(&s->gb, 1);
if (s->lfe > 2) {
s->lfe = 0;
av_log(s->avctx, AV_LOG_ERROR, "Invalid LFE value: %d\n", s->lfe);
return AVERROR_INVALIDDATA;
}
/* TODO: check CRC */
if (s->crc_present)
s->header_crc = get_bits(&s->gb, 16);
s->multirate_inter = get_bits(&s->gb, 1);
s->version = get_bits(&s->gb, 4);
s->copy_history = get_bits(&s->gb, 2);
s->source_pcm_res = get_bits(&s->gb, 3);
s->front_sum = get_bits(&s->gb, 1);
s->surround_sum = get_bits(&s->gb, 1);
s->dialog_norm = get_bits(&s->gb, 4);
/* FIXME: channels mixing levels */
s->output = s->amode;
if (s->lfe)
s->output |= DCA_LFE;
/* Primary audio coding header */
s->audio_header.subframes = get_bits(&s->gb, 4) + 1;
return dca_parse_audio_coding_header(s, 0, 0);
}
static inline int get_scale(GetBitContext *gb, int level, int value, int log2range)
{
if (level < 5) {
/* huffman encoded */
value += get_bitalloc(gb, &dca_scalefactor, level);
value = av_clip(value, 0, (1 << log2range) - 1);
} else if (level < 8) {
if (level + 1 > log2range) {
skip_bits(gb, level + 1 - log2range);
value = get_bits(gb, log2range);
} else {
value = get_bits(gb, level + 1);
}
}
return value;
}
static int dca_subframe_header(DCAContext *s, int base_channel, int block_index)
{
/* Primary audio coding side information */
int j, k;
if (get_bits_left(&s->gb) < 0)
return AVERROR_INVALIDDATA;
if (!base_channel) {
s->subsubframes[s->current_subframe] = get_bits(&s->gb, 2) + 1;
if (block_index + s->subsubframes[s->current_subframe] > (s->sample_blocks / SAMPLES_PER_SUBBAND)) {
s->subsubframes[s->current_subframe] = 1;
return AVERROR_INVALIDDATA;
}
s->partial_samples[s->current_subframe] = get_bits(&s->gb, 3);
}
for (j = base_channel; j < s->audio_header.prim_channels; j++) {
for (k = 0; k < s->audio_header.subband_activity[j]; k++)
s->dca_chan[j].prediction_mode[k] = get_bits(&s->gb, 1);
}
/* Get prediction codebook */
for (j = base_channel; j < s->audio_header.prim_channels; j++) {
for (k = 0; k < s->audio_header.subband_activity[j]; k++) {
if (s->dca_chan[j].prediction_mode[k] > 0) {
/* (Prediction coefficient VQ address) */
s->dca_chan[j].prediction_vq[k] = get_bits(&s->gb, 12);
}
}
}
/* Bit allocation index */
for (j = base_channel; j < s->audio_header.prim_channels; j++) {
for (k = 0; k < s->audio_header.vq_start_subband[j]; k++) {
if (s->audio_header.bitalloc_huffman[j] == 6)
s->dca_chan[j].bitalloc[k] = get_bits(&s->gb, 5);
else if (s->audio_header.bitalloc_huffman[j] == 5)
s->dca_chan[j].bitalloc[k] = get_bits(&s->gb, 4);
else if (s->audio_header.bitalloc_huffman[j] == 7) {
av_log(s->avctx, AV_LOG_ERROR,
"Invalid bit allocation index\n");
return AVERROR_INVALIDDATA;
} else {
s->dca_chan[j].bitalloc[k] =
get_bitalloc(&s->gb, &dca_bitalloc_index, s->audio_header.bitalloc_huffman[j]);
}
if (s->dca_chan[j].bitalloc[k] > 26) {
ff_dlog(s->avctx, "bitalloc index [%i][%i] too big (%i)\n",
j, k, s->dca_chan[j].bitalloc[k]);
return AVERROR_INVALIDDATA;
}
}
}
/* Transition mode */
for (j = base_channel; j < s->audio_header.prim_channels; j++) {
for (k = 0; k < s->audio_header.subband_activity[j]; k++) {
s->dca_chan[j].transition_mode[k] = 0;
if (s->subsubframes[s->current_subframe] > 1 &&
k < s->audio_header.vq_start_subband[j] && s->dca_chan[j].bitalloc[k] > 0) {
s->dca_chan[j].transition_mode[k] =
get_bitalloc(&s->gb, &dca_tmode, s->audio_header.transient_huffman[j]);
}
}
}
if (get_bits_left(&s->gb) < 0)
return AVERROR_INVALIDDATA;
for (j = base_channel; j < s->audio_header.prim_channels; j++) {
const uint32_t *scale_table;
int scale_sum, log_size;
memset(s->dca_chan[j].scale_factor, 0,
s->audio_header.subband_activity[j] * sizeof(s->dca_chan[j].scale_factor[0][0]) * 2);
if (s->audio_header.scalefactor_huffman[j] == 6) {
scale_table = ff_dca_scale_factor_quant7;
log_size = 7;
} else {
scale_table = ff_dca_scale_factor_quant6;
log_size = 6;
}
/* When huffman coded, only the difference is encoded */
scale_sum = 0;
for (k = 0; k < s->audio_header.subband_activity[j]; k++) {
if (k >= s->audio_header.vq_start_subband[j] || s->dca_chan[j].bitalloc[k] > 0) {
scale_sum = get_scale(&s->gb, s->audio_header.scalefactor_huffman[j], scale_sum, log_size);
s->dca_chan[j].scale_factor[k][0] = scale_table[scale_sum];
}
if (k < s->audio_header.vq_start_subband[j] && s->dca_chan[j].transition_mode[k]) {
/* Get second scale factor */
scale_sum = get_scale(&s->gb, s->audio_header.scalefactor_huffman[j], scale_sum, log_size);
s->dca_chan[j].scale_factor[k][1] = scale_table[scale_sum];
}
}
}
/* Joint subband scale factor codebook select */
for (j = base_channel; j < s->audio_header.prim_channels; j++) {
/* Transmitted only if joint subband coding enabled */
if (s->audio_header.joint_intensity[j] > 0)
s->dca_chan[j].joint_huff = get_bits(&s->gb, 3);
}
if (get_bits_left(&s->gb) < 0)
return AVERROR_INVALIDDATA;
/* Scale factors for joint subband coding */
for (j = base_channel; j < s->audio_header.prim_channels; j++) {
int source_channel;
/* Transmitted only if joint subband coding enabled */
if (s->audio_header.joint_intensity[j] > 0) {
int scale = 0;
source_channel = s->audio_header.joint_intensity[j] - 1;
/* When huffman coded, only the difference is encoded
* (is this valid as well for joint scales ???) */
for (k = s->audio_header.subband_activity[j];
k < s->audio_header.subband_activity[source_channel]; k++) {
scale = get_scale(&s->gb, s->dca_chan[j].joint_huff, 64 /* bias */, 7);
s->dca_chan[j].joint_scale_factor[k] = scale; /*joint_scale_table[scale]; */
}
if (!(s->debug_flag & 0x02)) {
av_log(s->avctx, AV_LOG_DEBUG,
"Joint stereo coding not supported\n");
s->debug_flag |= 0x02;
}
}
}
/* Dynamic range coefficient */
if (!base_channel && s->dynrange)
s->dynrange_coef = get_bits(&s->gb, 8);
/* Side information CRC check word */
if (s->crc_present) {
get_bits(&s->gb, 16);
}
/*
* Primary audio data arrays
*/
/* VQ encoded high frequency subbands */
for (j = base_channel; j < s->audio_header.prim_channels; j++)
for (k = s->audio_header.vq_start_subband[j]; k < s->audio_header.subband_activity[j]; k++)
/* 1 vector -> 32 samples */
s->dca_chan[j].high_freq_vq[k] = get_bits(&s->gb, 10);
/* Low frequency effect data */
if (!base_channel && s->lfe) {
int quant7;
/* LFE samples */
int lfe_samples = 2 * s->lfe * (4 + block_index);
int lfe_end_sample = 2 * s->lfe * (4 + block_index + s->subsubframes[s->current_subframe]);
float lfe_scale;
for (j = lfe_samples; j < lfe_end_sample; j++) {
/* Signed 8 bits int */
s->lfe_data[j] = get_sbits(&s->gb, 8);
}
/* Scale factor index */
quant7 = get_bits(&s->gb, 8);
if (quant7 > 127) {
avpriv_request_sample(s->avctx, "LFEScaleIndex larger than 127");
return AVERROR_INVALIDDATA;
}
s->lfe_scale_factor = ff_dca_scale_factor_quant7[quant7];
/* Quantization step size * scale factor */
lfe_scale = 0.035 * s->lfe_scale_factor;
for (j = lfe_samples; j < lfe_end_sample; j++)
s->lfe_data[j] *= lfe_scale;
}
return 0;
}
static void qmf_32_subbands(DCAContext *s, int chans,
float samples_in[DCA_SUBBANDS][SAMPLES_PER_SUBBAND], float *samples_out,
float scale)
{
const float *prCoeff;
int sb_act = s->audio_header.subband_activity[chans];
scale *= sqrt(1 / 8.0);
/* Select filter */
if (!s->multirate_inter) /* Non-perfect reconstruction */
prCoeff = ff_dca_fir_32bands_nonperfect;
else /* Perfect reconstruction */
prCoeff = ff_dca_fir_32bands_perfect;
s->dcadsp.qmf_32_subbands(samples_in, sb_act, &s->synth, &s->imdct,
s->dca_chan[chans].subband_fir_hist,
&s->dca_chan[chans].hist_index,
s->dca_chan[chans].subband_fir_noidea, prCoeff,
samples_out, s->raXin, scale);
}
static QMF64_table *qmf64_precompute(void)
{
unsigned i, j;
QMF64_table *table = av_malloc(sizeof(*table));
if (!table)
return NULL;
for (i = 0; i < 32; i++)
for (j = 0; j < 32; j++)
table->dct4_coeff[i][j] = cos((2 * i + 1) * (2 * j + 1) * M_PI / 128);
for (i = 0; i < 32; i++)
for (j = 0; j < 32; j++)
table->dct2_coeff[i][j] = cos((2 * i + 1) * j * M_PI / 64);
/* FIXME: Is the factor 0.125 = 1/8 right? */
for (i = 0; i < 32; i++)
table->rcos[i] = 0.125 / cos((2 * i + 1) * M_PI / 256);
for (i = 0; i < 32; i++)
table->rsin[i] = -0.125 / sin((2 * i + 1) * M_PI / 256);
return table;
}
/* FIXME: Totally unoptimized. Based on the reference code and
* http://multimedia.cx/mirror/dca-transform.pdf, with guessed tweaks
* for doubling the size. */
static void qmf_64_subbands(DCAContext *s, int chans,
float samples_in[DCA_SUBBANDS_X96K][SAMPLES_PER_SUBBAND],
float *samples_out, float scale)
{
float raXin[64];
float A[32], B[32];
float *raX = s->dca_chan[chans].subband_fir_hist;
float *raZ = s->dca_chan[chans].subband_fir_noidea;
unsigned i, j, k, subindex;
for (i = s->audio_header.subband_activity[chans]; i < DCA_SUBBANDS_X96K; i++)
raXin[i] = 0.0;
for (subindex = 0; subindex < SAMPLES_PER_SUBBAND; subindex++) {
for (i = 0; i < s->audio_header.subband_activity[chans]; i++)
raXin[i] = samples_in[i][subindex];
for (k = 0; k < 32; k++) {
A[k] = 0.0;
for (i = 0; i < 32; i++)
A[k] += (raXin[2 * i] + raXin[2 * i + 1]) * s->qmf64_table->dct4_coeff[k][i];
}
for (k = 0; k < 32; k++) {
B[k] = raXin[0] * s->qmf64_table->dct2_coeff[k][0];
for (i = 1; i < 32; i++)
B[k] += (raXin[2 * i] + raXin[2 * i - 1]) * s->qmf64_table->dct2_coeff[k][i];
}
for (k = 0; k < 32; k++) {
raX[k] = s->qmf64_table->rcos[k] * (A[k] + B[k]);
raX[63 - k] = s->qmf64_table->rsin[k] * (A[k] - B[k]);
}
for (i = 0; i < DCA_SUBBANDS_X96K; i++) {
float out = raZ[i];
for (j = 0; j < 1024; j += 128)
out += ff_dca_fir_64bands[j + i] * (raX[j + i] - raX[j + 63 - i]);
*samples_out++ = out * scale;
}
for (i = 0; i < DCA_SUBBANDS_X96K; i++) {
float hist = 0.0;
for (j = 0; j < 1024; j += 128)
hist += ff_dca_fir_64bands[64 + j + i] * (-raX[i + j] - raX[j + 63 - i]);
raZ[i] = hist;
}
/* FIXME: Make buffer circular, to avoid this move. */
memmove(raX + 64, raX, (1024 - 64) * sizeof(*raX));
}
}
static void lfe_interpolation_fir(DCAContext *s, const float *samples_in,
float *samples_out)
{
/* samples_in: An array holding decimated samples.
* Samples in current subframe starts from samples_in[0],
* while samples_in[-1], samples_in[-2], ..., stores samples
* from last subframe as history.
*
* samples_out: An array holding interpolated samples
*/
int idx;
const float *prCoeff;
int deciindex;
/* Select decimation filter */
if (s->lfe == 1) {
idx = 1;
prCoeff = ff_dca_lfe_fir_128;
} else {
idx = 0;
if (s->exss_ext_mask & DCA_EXT_EXSS_XLL)
prCoeff = ff_dca_lfe_xll_fir_64;
else
prCoeff = ff_dca_lfe_fir_64;
}
/* Interpolation */
for (deciindex = 0; deciindex < 2 * s->lfe; deciindex++) {
s->dcadsp.lfe_fir[idx](samples_out, samples_in, prCoeff);
samples_in++;
samples_out += 2 * 32 * (1 + idx);
}
}
/* downmixing routines */
#define MIX_REAR1(samples, s1, rs, coef) \
samples[0][i] += samples[s1][i] * coef[rs][0]; \
samples[1][i] += samples[s1][i] * coef[rs][1];
#define MIX_REAR2(samples, s1, s2, rs, coef) \
samples[0][i] += samples[s1][i] * coef[rs][0] + samples[s2][i] * coef[rs + 1][0]; \
samples[1][i] += samples[s1][i] * coef[rs][1] + samples[s2][i] * coef[rs + 1][1];
#define MIX_FRONT3(samples, coef) \
t = samples[c][i]; \
u = samples[l][i]; \
v = samples[r][i]; \
samples[0][i] = t * coef[0][0] + u * coef[1][0] + v * coef[2][0]; \
samples[1][i] = t * coef[0][1] + u * coef[1][1] + v * coef[2][1];
#define DOWNMIX_TO_STEREO(op1, op2) \
for (i = 0; i < 256; i++) { \
op1 \
op2 \
}
static void dca_downmix(float **samples, int srcfmt, int lfe_present,
float coef[DCA_PRIM_CHANNELS_MAX + 1][2],
const int8_t *channel_mapping)
{
int c, l, r, sl, sr, s;
int i;
float t, u, v;
switch (srcfmt) {
case DCA_MONO:
case DCA_4F2R:
av_log(NULL, AV_LOG_ERROR, "Not implemented!\n");
break;
case DCA_CHANNEL:
case DCA_STEREO:
case DCA_STEREO_TOTAL:
case DCA_STEREO_SUMDIFF:
break;
case DCA_3F:
c = channel_mapping[0];
l = channel_mapping[1];
r = channel_mapping[2];
DOWNMIX_TO_STEREO(MIX_FRONT3(samples, coef), );
break;
case DCA_2F1R:
s = channel_mapping[2];
DOWNMIX_TO_STEREO(MIX_REAR1(samples, s, 2, coef), );
break;
case DCA_3F1R:
c = channel_mapping[0];
l = channel_mapping[1];
r = channel_mapping[2];
s = channel_mapping[3];
DOWNMIX_TO_STEREO(MIX_FRONT3(samples, coef),
MIX_REAR1(samples, s, 3, coef));
break;
case DCA_2F2R:
sl = channel_mapping[2];
sr = channel_mapping[3];
DOWNMIX_TO_STEREO(MIX_REAR2(samples, sl, sr, 2, coef), );
break;
case DCA_3F2R:
c = channel_mapping[0];
l = channel_mapping[1];
r = channel_mapping[2];
sl = channel_mapping[3];
sr = channel_mapping[4];
DOWNMIX_TO_STEREO(MIX_FRONT3(samples, coef),
MIX_REAR2(samples, sl, sr, 3, coef));
break;
}
if (lfe_present) {
int lf_buf = ff_dca_lfe_index[srcfmt];
int lf_idx = ff_dca_channels[srcfmt];
for (i = 0; i < 256; i++) {
samples[0][i] += samples[lf_buf][i] * coef[lf_idx][0];
samples[1][i] += samples[lf_buf][i] * coef[lf_idx][1];
}
}
}
#ifndef decode_blockcodes
/* Very compact version of the block code decoder that does not use table
* look-up but is slightly slower */
static int decode_blockcode(int code, int levels, int32_t *values)
{
int i;
int offset = (levels - 1) >> 1;
for (i = 0; i < 4; i++) {
int div = FASTDIV(code, levels);
values[i] = code - offset - div * levels;
code = div;
}
return code;
}
static int decode_blockcodes(int code1, int code2, int levels, int32_t *values)
{
return decode_blockcode(code1, levels, values) |
decode_blockcode(code2, levels, values + 4);
}
#endif
static const uint8_t abits_sizes[7] = { 7, 10, 12, 13, 15, 17, 19 };
static const uint8_t abits_levels[7] = { 3, 5, 7, 9, 13, 17, 25 };
static int dca_subsubframe(DCAContext *s, int base_channel, int block_index)
{
int k, l;
int subsubframe = s->current_subsubframe;
const uint32_t *quant_step_table;
/*
* Audio data
*/
/* Select quantization step size table */
if (s->bit_rate_index == 0x1f)
quant_step_table = ff_dca_lossless_quant;
else
quant_step_table = ff_dca_lossy_quant;
for (k = base_channel; k < s->audio_header.prim_channels; k++) {
int32_t (*subband_samples)[8] = s->dca_chan[k].subband_samples[block_index];
if (get_bits_left(&s->gb) < 0)
return AVERROR_INVALIDDATA;
for (l = 0; l < s->audio_header.vq_start_subband[k]; l++) {
int m;
/* Select the mid-tread linear quantizer */
int abits = s->dca_chan[k].bitalloc[l];
uint32_t quant_step_size = quant_step_table[abits];
/*
* Extract bits from the bit stream
*/
if (!abits)
memset(subband_samples[l], 0, SAMPLES_PER_SUBBAND *
sizeof(subband_samples[l][0]));
else {
uint32_t rscale;
/* Deal with transients */
int sfi = s->dca_chan[k].transition_mode[l] &&
subsubframe >= s->dca_chan[k].transition_mode[l];
/* Determine quantization index code book and its type.
Select quantization index code book */
int sel = s->audio_header.quant_index_huffman[k][abits];
rscale = (s->dca_chan[k].scale_factor[l][sfi] *
s->audio_header.scalefactor_adj[k][sel] + 8) >> 4;
if (abits >= 11 || !dca_smpl_bitalloc[abits].vlc[sel].table) {
if (abits <= 7) {
/* Block code */
int block_code1, block_code2, size, levels, err;
size = abits_sizes[abits - 1];
levels = abits_levels[abits - 1];
block_code1 = get_bits(&s->gb, size);
block_code2 = get_bits(&s->gb, size);
err = decode_blockcodes(block_code1, block_code2,
levels, subband_samples[l]);
if (err) {
av_log(s->avctx, AV_LOG_ERROR,
"ERROR: block code look-up failed\n");
return AVERROR_INVALIDDATA;
}
} else {
/* no coding */
for (m = 0; m < SAMPLES_PER_SUBBAND; m++)
subband_samples[l][m] = get_sbits(&s->gb, abits - 3);
}
} else {
/* Huffman coded */
for (m = 0; m < SAMPLES_PER_SUBBAND; m++)
subband_samples[l][m] = get_bitalloc(&s->gb,
&dca_smpl_bitalloc[abits], sel);
}
s->dcadsp.dequantize(subband_samples[l], quant_step_size, rscale);
}
}
for (l = 0; l < s->audio_header.vq_start_subband[k]; l++) {
int m;
/*
* Inverse ADPCM if in prediction mode
*/
if (s->dca_chan[k].prediction_mode[l]) {
int n;
if (s->predictor_history)
subband_samples[l][0] += (ff_dca_adpcm_vb[s->dca_chan[k].prediction_vq[l]][0] *
(int64_t)s->dca_chan[k].subband_samples_hist[l][3] +
ff_dca_adpcm_vb[s->dca_chan[k].prediction_vq[l]][1] *
(int64_t)s->dca_chan[k].subband_samples_hist[l][2] +
ff_dca_adpcm_vb[s->dca_chan[k].prediction_vq[l]][2] *
(int64_t)s->dca_chan[k].subband_samples_hist[l][1] +
ff_dca_adpcm_vb[s->dca_chan[k].prediction_vq[l]][3] *
(int64_t)s->dca_chan[k].subband_samples_hist[l][0]) +
(1 << 12) >> 13;
for (m = 1; m < SAMPLES_PER_SUBBAND; m++) {
int64_t sum = ff_dca_adpcm_vb[s->dca_chan[k].prediction_vq[l]][0] *
(int64_t)subband_samples[l][m - 1];
for (n = 2; n <= 4; n++)
if (m >= n)
sum += ff_dca_adpcm_vb[s->dca_chan[k].prediction_vq[l]][n - 1] *
(int64_t)subband_samples[l][m - n];
else if (s->predictor_history)
sum += ff_dca_adpcm_vb[s->dca_chan[k].prediction_vq[l]][n - 1] *
(int64_t)s->dca_chan[k].subband_samples_hist[l][m - n + 4];
subband_samples[l][m] += (int32_t)(sum + (1 << 12) >> 13);
}
}
}
/* Backup predictor history for adpcm */
for (l = 0; l < DCA_SUBBANDS; l++)
AV_COPY128(s->dca_chan[k].subband_samples_hist[l], &subband_samples[l][4]);
/*
* Decode VQ encoded high frequencies
*/
if (s->audio_header.subband_activity[k] > s->audio_header.vq_start_subband[k]) {
if (!(s->debug_flag & 0x01)) {
av_log(s->avctx, AV_LOG_DEBUG,
"Stream with high frequencies VQ coding\n");
s->debug_flag |= 0x01;
}
s->dcadsp.decode_hf(subband_samples, s->dca_chan[k].high_freq_vq,
ff_dca_high_freq_vq,
subsubframe * SAMPLES_PER_SUBBAND,
s->dca_chan[k].scale_factor,
s->audio_header.vq_start_subband[k],
s->audio_header.subband_activity[k]);
}
}
/* Check for DSYNC after subsubframe */
if (s->aspf || subsubframe == s->subsubframes[s->current_subframe] - 1) {
if (get_bits(&s->gb, 16) != 0xFFFF) {
av_log(s->avctx, AV_LOG_ERROR, "Didn't get subframe DSYNC\n");
return AVERROR_INVALIDDATA;
}
}
return 0;
}
static int dca_filter_channels(DCAContext *s, int block_index, int upsample)
{
int k;
if (upsample) {
LOCAL_ALIGNED(32, float, samples, [DCA_SUBBANDS_X96K], [SAMPLES_PER_SUBBAND]);
if (!s->qmf64_table) {
s->qmf64_table = qmf64_precompute();
if (!s->qmf64_table)
return AVERROR(ENOMEM);
}
/* 64 subbands QMF */
for (k = 0; k < s->audio_header.prim_channels; k++) {
int32_t (*subband_samples)[SAMPLES_PER_SUBBAND] =
s->dca_chan[k].subband_samples[block_index];
s->fmt_conv.int32_to_float(samples[0], subband_samples[0],
DCA_SUBBANDS_X96K * SAMPLES_PER_SUBBAND);
if (s->channel_order_tab[k] >= 0)
qmf_64_subbands(s, k, samples,
s->samples_chanptr[s->channel_order_tab[k]],
/* Upsampling needs a factor 2 here. */
M_SQRT2 / 32768.0);
}
} else {
/* 32 subbands QMF */
LOCAL_ALIGNED(32, float, samples, [DCA_SUBBANDS], [SAMPLES_PER_SUBBAND]);
for (k = 0; k < s->audio_header.prim_channels; k++) {
int32_t (*subband_samples)[SAMPLES_PER_SUBBAND] =
s->dca_chan[k].subband_samples[block_index];
s->fmt_conv.int32_to_float(samples[0], subband_samples[0],
DCA_SUBBANDS * SAMPLES_PER_SUBBAND);
if (s->channel_order_tab[k] >= 0)
qmf_32_subbands(s, k, samples,
s->samples_chanptr[s->channel_order_tab[k]],
M_SQRT1_2 / 32768.0);
}
}
/* Generate LFE samples for this subsubframe FIXME!!! */
if (s->lfe) {
float *samples = s->samples_chanptr[s->lfe_index];
lfe_interpolation_fir(s,
s->lfe_data + 2 * s->lfe * (block_index + 4),
samples);
if (upsample) {
unsigned i;
/* Should apply the filter in Table 6-11 when upsampling. For
* now, just duplicate. */
for (i = 255; i > 0; i--) {
samples[2 * i] =
samples[2 * i + 1] = samples[i];
}
samples[1] = samples[0];
}
}
/* FIXME: This downmixing is probably broken with upsample.
* Probably totally broken also with XLL in general. */
/* Downmixing to Stereo */
if (s->audio_header.prim_channels + !!s->lfe > 2 &&
s->avctx->request_channel_layout == AV_CH_LAYOUT_STEREO) {
dca_downmix(s->samples_chanptr, s->amode, !!s->lfe, s->downmix_coef,
s->channel_order_tab);
}
return 0;
}
static int dca_subframe_footer(DCAContext *s, int base_channel)
{
int in, out, aux_data_count, aux_data_end, reserved;
uint32_t nsyncaux;
/*
* Unpack optional information
*/
/* presumably optional information only appears in the core? */
if (!base_channel) {
if (s->timestamp)
skip_bits_long(&s->gb, 32);
if (s->aux_data) {
aux_data_count = get_bits(&s->gb, 6);
// align (32-bit)
skip_bits_long(&s->gb, (-get_bits_count(&s->gb)) & 31);
aux_data_end = 8 * aux_data_count + get_bits_count(&s->gb);
if ((nsyncaux = get_bits_long(&s->gb, 32)) != DCA_NSYNCAUX) {
av_log(s->avctx, AV_LOG_ERROR, "nSYNCAUX mismatch %#"PRIx32"\n",
nsyncaux);
return AVERROR_INVALIDDATA;
}
if (get_bits1(&s->gb)) { // bAUXTimeStampFlag
avpriv_request_sample(s->avctx,
"Auxiliary Decode Time Stamp Flag");
// align (4-bit)
skip_bits(&s->gb, (-get_bits_count(&s->gb)) & 4);
// 44 bits: nMSByte (8), nMarker (4), nLSByte (28), nMarker (4)
skip_bits_long(&s->gb, 44);
}
if ((s->core_downmix = get_bits1(&s->gb))) {
int am = get_bits(&s->gb, 3);
switch (am) {
case 0:
s->core_downmix_amode = DCA_MONO;
break;
case 1:
s->core_downmix_amode = DCA_STEREO;
break;
case 2:
s->core_downmix_amode = DCA_STEREO_TOTAL;
break;
case 3:
s->core_downmix_amode = DCA_3F;
break;
case 4:
s->core_downmix_amode = DCA_2F1R;
break;
case 5:
s->core_downmix_amode = DCA_2F2R;
break;
case 6:
s->core_downmix_amode = DCA_3F1R;
break;
default:
av_log(s->avctx, AV_LOG_ERROR,
"Invalid mode %d for embedded downmix coefficients\n",
am);
return AVERROR_INVALIDDATA;
}
for (out = 0; out < ff_dca_channels[s->core_downmix_amode]; out++) {
for (in = 0; in < s->audio_header.prim_channels + !!s->lfe; in++) {
uint16_t tmp = get_bits(&s->gb, 9);
if ((tmp & 0xFF) > 241) {
av_log(s->avctx, AV_LOG_ERROR,
"Invalid downmix coefficient code %"PRIu16"\n",
tmp);
return AVERROR_INVALIDDATA;
}
s->core_downmix_codes[in][out] = tmp;
}
}
}
align_get_bits(&s->gb); // byte align
skip_bits(&s->gb, 16); // nAUXCRC16
/*
* additional data (reserved, cf. ETSI TS 102 114 V1.4.1)
*
* Note: don't check for overreads, aux_data_count can't be trusted.
*/
if ((reserved = (aux_data_end - get_bits_count(&s->gb))) > 0) {
avpriv_request_sample(s->avctx,
"Core auxiliary data reserved content");
skip_bits_long(&s->gb, reserved);
}
}
if (s->crc_present && s->dynrange)
get_bits(&s->gb, 16);
}
return 0;
}
/**
* Decode a dca frame block
*
* @param s pointer to the DCAContext
*/
static int dca_decode_block(DCAContext *s, int base_channel, int block_index)
{
int ret;
/* Sanity check */
if (s->current_subframe >= s->audio_header.subframes) {
av_log(s->avctx, AV_LOG_DEBUG, "check failed: %i>%i",
s->current_subframe, s->audio_header.subframes);
return AVERROR_INVALIDDATA;
}
if (!s->current_subsubframe) {
/* Read subframe header */
if ((ret = dca_subframe_header(s, base_channel, block_index)))
return ret;
}
/* Read subsubframe */
if ((ret = dca_subsubframe(s, base_channel, block_index)))
return ret;
/* Update state */
s->current_subsubframe++;
if (s->current_subsubframe >= s->subsubframes[s->current_subframe]) {
s->current_subsubframe = 0;
s->current_subframe++;
}
if (s->current_subframe >= s->audio_header.subframes) {
/* Read subframe footer */
if ((ret = dca_subframe_footer(s, base_channel)))
return ret;
}
return 0;
}
int ff_dca_xbr_parse_frame(DCAContext *s)
{
int scale_table_high[DCA_CHSET_CHANS_MAX][DCA_SUBBANDS][2];
int active_bands[DCA_CHSETS_MAX][DCA_CHSET_CHANS_MAX];
int abits_high[DCA_CHSET_CHANS_MAX][DCA_SUBBANDS];
int anctemp[DCA_CHSET_CHANS_MAX];
int chset_fsize[DCA_CHSETS_MAX];
int n_xbr_ch[DCA_CHSETS_MAX];
int hdr_size, num_chsets, xbr_tmode, hdr_pos;
int i, j, k, l, chset, chan_base;
av_log(s->avctx, AV_LOG_DEBUG, "DTS-XBR: decoding XBR extension\n");
/* get bit position of sync header */
hdr_pos = get_bits_count(&s->gb) - 32;
hdr_size = get_bits(&s->gb, 6) + 1;
num_chsets = get_bits(&s->gb, 2) + 1;
for(i = 0; i < num_chsets; i++)
chset_fsize[i] = get_bits(&s->gb, 14) + 1;
xbr_tmode = get_bits1(&s->gb);
for(i = 0; i < num_chsets; i++) {
n_xbr_ch[i] = get_bits(&s->gb, 3) + 1;
k = get_bits(&s->gb, 2) + 5;
for(j = 0; j < n_xbr_ch[i]; j++) {
active_bands[i][j] = get_bits(&s->gb, k) + 1;
if (active_bands[i][j] > DCA_SUBBANDS) {
av_log(s->avctx, AV_LOG_ERROR, "too many active subbands (%d)\n", active_bands[i][j]);
return AVERROR_INVALIDDATA;
}
}
}
/* skip to the end of the header */
i = get_bits_count(&s->gb);
if(hdr_pos + hdr_size * 8 > i)
skip_bits_long(&s->gb, hdr_pos + hdr_size * 8 - i);
/* loop over the channel data sets */
/* only decode as many channels as we've decoded base data for */
for(chset = 0, chan_base = 0;
chset < num_chsets && chan_base + n_xbr_ch[chset] <= s->audio_header.prim_channels;
chan_base += n_xbr_ch[chset++]) {
int start_posn = get_bits_count(&s->gb);
int subsubframe = 0;
int subframe = 0;
/* loop over subframes */
for (k = 0; k < (s->sample_blocks / 8); k++) {
/* parse header if we're on first subsubframe of a block */
if(subsubframe == 0) {
/* Parse subframe header */
for(i = 0; i < n_xbr_ch[chset]; i++) {
anctemp[i] = get_bits(&s->gb, 2) + 2;
}
for(i = 0; i < n_xbr_ch[chset]; i++) {
get_array(&s->gb, abits_high[i], active_bands[chset][i], anctemp[i]);
}
for(i = 0; i < n_xbr_ch[chset]; i++) {
anctemp[i] = get_bits(&s->gb, 3);
if(anctemp[i] < 1) {
av_log(s->avctx, AV_LOG_ERROR, "DTS-XBR: SYNC ERROR\n");
return AVERROR_INVALIDDATA;
}
}
/* generate scale factors */
for(i = 0; i < n_xbr_ch[chset]; i++) {
const uint32_t *scale_table;
int nbits;
int scale_table_size;
if (s->audio_header.scalefactor_huffman[chan_base+i] == 6) {
scale_table = ff_dca_scale_factor_quant7;
scale_table_size = FF_ARRAY_ELEMS(ff_dca_scale_factor_quant7);
} else {
scale_table = ff_dca_scale_factor_quant6;
scale_table_size = FF_ARRAY_ELEMS(ff_dca_scale_factor_quant6);
}
nbits = anctemp[i];
for(j = 0; j < active_bands[chset][i]; j++) {
if(abits_high[i][j] > 0) {
int index = get_bits(&s->gb, nbits);
if (index >= scale_table_size) {
av_log(s->avctx, AV_LOG_ERROR, "scale table index %d invalid\n", index);
return AVERROR_INVALIDDATA;
}
scale_table_high[i][j][0] = scale_table[index];
if(xbr_tmode && s->dca_chan[i].transition_mode[j]) {
int index = get_bits(&s->gb, nbits);
if (index >= scale_table_size) {
av_log(s->avctx, AV_LOG_ERROR, "scale table index %d invalid\n", index);
return AVERROR_INVALIDDATA;
}
scale_table_high[i][j][1] = scale_table[index];
}
}
}
}
}
/* decode audio array for this block */
for(i = 0; i < n_xbr_ch[chset]; i++) {
for(j = 0; j < active_bands[chset][i]; j++) {
const int xbr_abits = abits_high[i][j];
const uint32_t quant_step_size = ff_dca_lossless_quant[xbr_abits];
const int sfi = xbr_tmode && s->dca_chan[i].transition_mode[j] && subsubframe >= s->dca_chan[i].transition_mode[j];
const uint32_t rscale = scale_table_high[i][j][sfi];
int32_t *subband_samples = s->dca_chan[chan_base+i].subband_samples[k][j];
int32_t block[SAMPLES_PER_SUBBAND];
if(xbr_abits <= 0)
continue;
if(xbr_abits > 7) {
get_array(&s->gb, block, SAMPLES_PER_SUBBAND, xbr_abits - 3);
} else {
int block_code1, block_code2, size, levels, err;
size = abits_sizes[xbr_abits - 1];
levels = abits_levels[xbr_abits - 1];
block_code1 = get_bits(&s->gb, size);
block_code2 = get_bits(&s->gb, size);
err = decode_blockcodes(block_code1, block_code2,
levels, block);
if (err) {
av_log(s->avctx, AV_LOG_ERROR,
"ERROR: DTS-XBR: block code look-up failed\n");
return AVERROR_INVALIDDATA;
}
}
/* scale & sum into subband */
s->dcadsp.dequantize(block, quant_step_size, rscale);
for(l = 0; l < SAMPLES_PER_SUBBAND; l++)
subband_samples[l] += block[l];
}
}
/* check DSYNC marker */
if(s->aspf || subsubframe == s->subsubframes[subframe] - 1) {
if(get_bits(&s->gb, 16) != 0xffff) {
av_log(s->avctx, AV_LOG_ERROR, "DTS-XBR: Didn't get subframe DSYNC\n");
return AVERROR_INVALIDDATA;
}
}
/* advance sub-sub-frame index */
if(++subsubframe >= s->subsubframes[subframe]) {
subsubframe = 0;
subframe++;
}
}
/* skip to next channel set */
i = get_bits_count(&s->gb);
if(start_posn + chset_fsize[chset] * 8 != i) {
j = start_posn + chset_fsize[chset] * 8 - i;
if(j < 0 || j >= 8)
av_log(s->avctx, AV_LOG_ERROR, "DTS-XBR: end of channel set,"
" skipping further than expected (%d bits)\n", j);
skip_bits_long(&s->gb, j);
}
}
return 0;
}
/* parse initial header for XXCH and dump details */
int ff_dca_xxch_decode_frame(DCAContext *s)
{
int hdr_size, spkmsk_bits, num_chsets, core_spk, hdr_pos;
int i, chset, base_channel, chstart, fsize[8];
/* assume header word has already been parsed */
hdr_pos = get_bits_count(&s->gb) - 32;
hdr_size = get_bits(&s->gb, 6) + 1;
/*chhdr_crc =*/ skip_bits1(&s->gb);
spkmsk_bits = get_bits(&s->gb, 5) + 1;
num_chsets = get_bits(&s->gb, 2) + 1;
for (i = 0; i < num_chsets; i++)
fsize[i] = get_bits(&s->gb, 14) + 1;
core_spk = get_bits(&s->gb, spkmsk_bits);
s->xxch_core_spkmask = core_spk;
s->xxch_nbits_spk_mask = spkmsk_bits;
s->xxch_dmix_embedded = 0;
/* skip to the end of the header */
i = get_bits_count(&s->gb);
if (hdr_pos + hdr_size * 8 > i)
skip_bits_long(&s->gb, hdr_pos + hdr_size * 8 - i);
for (chset = 0; chset < num_chsets; chset++) {
chstart = get_bits_count(&s->gb);
base_channel = s->audio_header.prim_channels;
s->xxch_chset = chset;
/* XXCH and Core headers differ, see 6.4.2 "XXCH Channel Set Header" vs.
5.3.2 "Primary Audio Coding Header", DTS Spec 1.3.1 */
dca_parse_audio_coding_header(s, base_channel, 1);
/* decode channel data */
for (i = 0; i < (s->sample_blocks / 8); i++) {
if (dca_decode_block(s, base_channel, i)) {
av_log(s->avctx, AV_LOG_ERROR,
"Error decoding DTS-XXCH extension\n");
continue;
}
}
/* skip to end of this section */
i = get_bits_count(&s->gb);
if (chstart + fsize[chset] * 8 > i)
skip_bits_long(&s->gb, chstart + fsize[chset] * 8 - i);
}
s->xxch_chset = num_chsets;
return 0;
}
static float dca_dmix_code(unsigned code)
{
int sign = (code >> 8) - 1;
code &= 0xff;
return ((ff_dca_dmixtable[code] ^ sign) - sign) * (1.0 / (1 << 15));
}
static int scan_for_extensions(AVCodecContext *avctx)
{
DCAContext *s = avctx->priv_data;
int core_ss_end, ret = 0;
core_ss_end = FFMIN(s->frame_size, s->dca_buffer_size) * 8;
/* only scan for extensions if ext_descr was unknown or indicated a
* supported XCh extension */
if (s->core_ext_mask < 0 || s->core_ext_mask & (DCA_EXT_XCH | DCA_EXT_XXCH)) {
/* if ext_descr was unknown, clear s->core_ext_mask so that the
* extensions scan can fill it up */
s->core_ext_mask = FFMAX(s->core_ext_mask, 0);
/* extensions start at 32-bit boundaries into bitstream */
skip_bits_long(&s->gb, (-get_bits_count(&s->gb)) & 31);
while (core_ss_end - get_bits_count(&s->gb) >= 32) {
uint32_t bits = get_bits_long(&s->gb, 32);
int i;
switch (bits) {
case DCA_SYNCWORD_XCH: {
int ext_amode, xch_fsize;
s->xch_base_channel = s->audio_header.prim_channels;
/* validate sync word using XCHFSIZE field */
xch_fsize = show_bits(&s->gb, 10);
if ((s->frame_size != (get_bits_count(&s->gb) >> 3) - 4 + xch_fsize) &&
(s->frame_size != (get_bits_count(&s->gb) >> 3) - 4 + xch_fsize + 1))
continue;
/* skip length-to-end-of-frame field for the moment */
skip_bits(&s->gb, 10);
s->core_ext_mask |= DCA_EXT_XCH;
/* extension amode(number of channels in extension) should be 1 */
/* AFAIK XCh is not used for more channels */
if ((ext_amode = get_bits(&s->gb, 4)) != 1) {
av_log(avctx, AV_LOG_ERROR,
"XCh extension amode %d not supported!\n",
ext_amode);
continue;
}
if (s->xch_base_channel < 2) {
avpriv_request_sample(avctx, "XCh with fewer than 2 base channels");
continue;
}
/* much like core primary audio coding header */
dca_parse_audio_coding_header(s, s->xch_base_channel, 0);
for (i = 0; i < (s->sample_blocks / 8); i++)
if ((ret = dca_decode_block(s, s->xch_base_channel, i))) {
av_log(avctx, AV_LOG_ERROR, "error decoding XCh extension\n");
continue;
}
s->xch_present = 1;
break;
}
case DCA_SYNCWORD_XXCH:
/* XXCh: extended channels */
/* usually found either in core or HD part in DTS-HD HRA streams,
* but not in DTS-ES which contains XCh extensions instead */
s->core_ext_mask |= DCA_EXT_XXCH;
ff_dca_xxch_decode_frame(s);
break;
case 0x1d95f262: {
int fsize96 = show_bits(&s->gb, 12) + 1;
if (s->frame_size != (get_bits_count(&s->gb) >> 3) - 4 + fsize96)
continue;
av_log(avctx, AV_LOG_DEBUG, "X96 extension found at %d bits\n",
get_bits_count(&s->gb));
skip_bits(&s->gb, 12);
av_log(avctx, AV_LOG_DEBUG, "FSIZE96 = %d bytes\n", fsize96);
av_log(avctx, AV_LOG_DEBUG, "REVNO = %d\n", get_bits(&s->gb, 4));
s->core_ext_mask |= DCA_EXT_X96;
break;
}
}
skip_bits_long(&s->gb, (-get_bits_count(&s->gb)) & 31);
}
} else {
/* no supported extensions, skip the rest of the core substream */
skip_bits_long(&s->gb, core_ss_end - get_bits_count(&s->gb));
}
if (s->core_ext_mask & DCA_EXT_X96)
s->profile = FF_PROFILE_DTS_96_24;
else if (s->core_ext_mask & (DCA_EXT_XCH | DCA_EXT_XXCH))
s->profile = FF_PROFILE_DTS_ES;
/* check for ExSS (HD part) */
if (s->dca_buffer_size - s->frame_size > 32 &&
get_bits_long(&s->gb, 32) == DCA_SYNCWORD_SUBSTREAM)
ff_dca_exss_parse_header(s);
return ret;
}
static int set_channel_layout(AVCodecContext *avctx, int *channels, int num_core_channels)
{
DCAContext *s = avctx->priv_data;
int i, j, chset, mask;
int channel_layout, channel_mask;
int posn, lavc;
/* If we have XXCH then the channel layout is managed differently */
/* note that XLL will also have another way to do things */
if (!(s->core_ext_mask & DCA_EXT_XXCH)) {
/* xxx should also do MA extensions */
if (s->amode < 16) {
avctx->channel_layout = ff_dca_core_channel_layout[s->amode];
if (s->audio_header.prim_channels + !!s->lfe > 2 &&
avctx->request_channel_layout == AV_CH_LAYOUT_STEREO) {
/*
* Neither the core's auxiliary data nor our default tables contain
* downmix coefficients for the additional channel coded in the XCh
* extension, so when we're doing a Stereo downmix, don't decode it.
*/
s->xch_disable = 1;
}
if (s->xch_present && !s->xch_disable) {
if (avctx->channel_layout & AV_CH_BACK_CENTER) {
avpriv_request_sample(avctx, "XCh with Back center channel");
return AVERROR_INVALIDDATA;
}
avctx->channel_layout |= AV_CH_BACK_CENTER;
if (s->lfe) {
avctx->channel_layout |= AV_CH_LOW_FREQUENCY;
s->channel_order_tab = ff_dca_channel_reorder_lfe_xch[s->amode];
} else {
s->channel_order_tab = ff_dca_channel_reorder_nolfe_xch[s->amode];
}
if (s->channel_order_tab[s->xch_base_channel] < 0)
return AVERROR_INVALIDDATA;
} else {
*channels = num_core_channels + !!s->lfe;
s->xch_present = 0; /* disable further xch processing */
if (s->lfe) {
avctx->channel_layout |= AV_CH_LOW_FREQUENCY;
s->channel_order_tab = ff_dca_channel_reorder_lfe[s->amode];
} else
s->channel_order_tab = ff_dca_channel_reorder_nolfe[s->amode];
}
if (*channels > !!s->lfe &&
s->channel_order_tab[*channels - 1 - !!s->lfe] < 0)
return AVERROR_INVALIDDATA;
if (av_get_channel_layout_nb_channels(avctx->channel_layout) != *channels) {
av_log(avctx, AV_LOG_ERROR, "Number of channels %d mismatches layout %d\n", *channels, av_get_channel_layout_nb_channels(avctx->channel_layout));
return AVERROR_INVALIDDATA;
}
if (num_core_channels + !!s->lfe > 2 &&
avctx->request_channel_layout == AV_CH_LAYOUT_STEREO) {
*channels = 2;
s->output = s->audio_header.prim_channels == 2 ? s->amode : DCA_STEREO;
avctx->channel_layout = AV_CH_LAYOUT_STEREO;
}
else if (avctx->request_channel_layout & AV_CH_LAYOUT_NATIVE) {
static const int8_t dca_channel_order_native[9] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
s->channel_order_tab = dca_channel_order_native;
}
s->lfe_index = ff_dca_lfe_index[s->amode];
} else {
av_log(avctx, AV_LOG_ERROR,
"Non standard configuration %d !\n", s->amode);
return AVERROR_INVALIDDATA;
}
s->xxch_dmix_embedded = 0;
} else {
/* we only get here if an XXCH channel set can be added to the mix */
channel_mask = s->xxch_core_spkmask;
{
*channels = s->audio_header.prim_channels + !!s->lfe;
for (i = 0; i < s->xxch_chset; i++) {
channel_mask |= s->xxch_spk_masks[i];
}
}
/* Given the DTS spec'ed channel mask, generate an avcodec version */
channel_layout = 0;
for (i = 0; i < s->xxch_nbits_spk_mask; ++i) {
if (channel_mask & (1 << i)) {
channel_layout |= ff_dca_map_xxch_to_native[i];
}
}
/* make sure that we have managed to get equivalent dts/avcodec channel
* masks in some sense -- unfortunately some channels could overlap */
if (av_popcount(channel_mask) != av_popcount(channel_layout)) {
av_log(avctx, AV_LOG_DEBUG,
"DTS-XXCH: Inconsistent avcodec/dts channel layouts\n");
return AVERROR_INVALIDDATA;
}
avctx->channel_layout = channel_layout;
if (!(avctx->request_channel_layout & AV_CH_LAYOUT_NATIVE)) {
/* Estimate DTS --> avcodec ordering table */
for (chset = -1, j = 0; chset < s->xxch_chset; ++chset) {
mask = chset >= 0 ? s->xxch_spk_masks[chset]
: s->xxch_core_spkmask;
for (i = 0; i < s->xxch_nbits_spk_mask; i++) {
if (mask & ~(DCA_XXCH_LFE1 | DCA_XXCH_LFE2) & (1 << i)) {
lavc = ff_dca_map_xxch_to_native[i];
posn = av_popcount(channel_layout & (lavc - 1));
s->xxch_order_tab[j++] = posn;
}
}
}
s->lfe_index = av_popcount(channel_layout & (AV_CH_LOW_FREQUENCY-1));
} else { /* native ordering */
for (i = 0; i < *channels; i++)
s->xxch_order_tab[i] = i;
s->lfe_index = *channels - 1;
}
s->channel_order_tab = s->xxch_order_tab;
}
return 0;
}
/**
* Main frame decoding function
* FIXME add arguments
*/
static int dca_decode_frame(AVCodecContext *avctx, void *data,
int *got_frame_ptr, AVPacket *avpkt)
{
AVFrame *frame = data;
const uint8_t *buf = avpkt->data;
int buf_size = avpkt->size;
int lfe_samples;
int num_core_channels = 0;
int i, ret;
float **samples_flt;
float *src_chan;
float *dst_chan;
DCAContext *s = avctx->priv_data;
int channels, full_channels;
float scale;
int achan;
int chset;
int mask;
int j, k;
int endch;
int upsample = 0;
s->exss_ext_mask = 0;
s->xch_present = 0;
s->dca_buffer_size = AVERROR_INVALIDDATA;
for (i = 0; i < buf_size - 3 && s->dca_buffer_size == AVERROR_INVALIDDATA; i++)
s->dca_buffer_size = avpriv_dca_convert_bitstream(buf + i, buf_size - i, s->dca_buffer,
DCA_MAX_FRAME_SIZE + DCA_MAX_EXSS_HEADER_SIZE);
if (s->dca_buffer_size == AVERROR_INVALIDDATA) {
av_log(avctx, AV_LOG_ERROR, "Not a valid DCA frame\n");
return AVERROR_INVALIDDATA;
}
if ((ret = dca_parse_frame_header(s)) < 0) {
// seems like the frame is corrupt, try with the next one
return ret;
}
// set AVCodec values with parsed data
avctx->sample_rate = s->sample_rate;
s->profile = FF_PROFILE_DTS;
for (i = 0; i < (s->sample_blocks / SAMPLES_PER_SUBBAND); i++) {
if ((ret = dca_decode_block(s, 0, i))) {
av_log(avctx, AV_LOG_ERROR, "error decoding block\n");
return ret;
}
}
/* record number of core channels incase less than max channels are requested */
num_core_channels = s->audio_header.prim_channels;
if (s->audio_header.prim_channels + !!s->lfe > 2 &&
avctx->request_channel_layout == AV_CH_LAYOUT_STEREO) {
/* Stereo downmix coefficients
*
* The decoder can only downmix to 2-channel, so we need to ensure
* embedded downmix coefficients are actually targeting 2-channel.
*/
if (s->core_downmix && (s->core_downmix_amode == DCA_STEREO ||
s->core_downmix_amode == DCA_STEREO_TOTAL)) {
for (i = 0; i < num_core_channels + !!s->lfe; i++) {
/* Range checked earlier */
s->downmix_coef[i][0] = dca_dmix_code(s->core_downmix_codes[i][0]);
s->downmix_coef[i][1] = dca_dmix_code(s->core_downmix_codes[i][1]);
}
s->output = s->core_downmix_amode;
} else {
int am = s->amode & DCA_CHANNEL_MASK;
if (am >= FF_ARRAY_ELEMS(ff_dca_default_coeffs)) {
av_log(s->avctx, AV_LOG_ERROR,
"Invalid channel mode %d\n", am);
return AVERROR_INVALIDDATA;
}
if (num_core_channels + !!s->lfe >
FF_ARRAY_ELEMS(ff_dca_default_coeffs[0])) {
avpriv_request_sample(s->avctx, "Downmixing %d channels",
s->audio_header.prim_channels + !!s->lfe);
return AVERROR_PATCHWELCOME;
}
for (i = 0; i < num_core_channels + !!s->lfe; i++) {
s->downmix_coef[i][0] = ff_dca_default_coeffs[am][i][0];
s->downmix_coef[i][1] = ff_dca_default_coeffs[am][i][1];
}
}
ff_dlog(s->avctx, "Stereo downmix coeffs:\n");
for (i = 0; i < num_core_channels + !!s->lfe; i++) {
ff_dlog(s->avctx, "L, input channel %d = %f\n", i,
s->downmix_coef[i][0]);
ff_dlog(s->avctx, "R, input channel %d = %f\n", i,
s->downmix_coef[i][1]);
}
ff_dlog(s->avctx, "\n");
}
if (s->ext_coding)
s->core_ext_mask = ff_dca_ext_audio_descr_mask[s->ext_descr];
else
s->core_ext_mask = 0;
ret = scan_for_extensions(avctx);
avctx->profile = s->profile;
full_channels = channels = s->audio_header.prim_channels + !!s->lfe;
ret = set_channel_layout(avctx, &channels, num_core_channels);
if (ret < 0)
return ret;
/* get output buffer */
frame->nb_samples = 256 * (s->sample_blocks / SAMPLES_PER_SUBBAND);
if (s->exss_ext_mask & DCA_EXT_EXSS_XLL) {
int xll_nb_samples = s->xll_segments * s->xll_smpl_in_seg;
/* Check for invalid/unsupported conditions first */
if (s->xll_residual_channels > channels) {
av_log(s->avctx, AV_LOG_WARNING,
"DCA: too many residual channels (%d, core channels %d). Disabling XLL\n",
s->xll_residual_channels, channels);
s->exss_ext_mask &= ~DCA_EXT_EXSS_XLL;
} else if (xll_nb_samples != frame->nb_samples &&
2 * frame->nb_samples != xll_nb_samples) {
av_log(s->avctx, AV_LOG_WARNING,
"DCA: unsupported upsampling (%d XLL samples, %d core samples). Disabling XLL\n",
xll_nb_samples, frame->nb_samples);
s->exss_ext_mask &= ~DCA_EXT_EXSS_XLL;
} else {
if (2 * frame->nb_samples == xll_nb_samples) {
av_log(s->avctx, AV_LOG_INFO,
"XLL: upsampling core channels by a factor of 2\n");
upsample = 1;
frame->nb_samples = xll_nb_samples;
// FIXME: Is it good enough to copy from the first channel set?
avctx->sample_rate = s->xll_chsets[0].sampling_frequency;
}
/* If downmixing to stereo, don't decode additional channels.
* FIXME: Using the xch_disable flag for this doesn't seem right. */
if (!s->xch_disable)
channels = s->xll_channels;
}
}
if (avctx->channels != channels) {
if (avctx->channels)
av_log(avctx, AV_LOG_INFO, "Number of channels changed in DCA decoder (%d -> %d)\n", avctx->channels, channels);
avctx->channels = channels;
}
/* FIXME: This is an ugly hack, to just revert to the default
* layout if we have additional channels. Need to convert the XLL
* channel masks to ffmpeg channel_layout mask. */
if (av_get_channel_layout_nb_channels(avctx->channel_layout) != avctx->channels)
avctx->channel_layout = 0;
if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
return ret;
samples_flt = (float **) frame->extended_data;
/* allocate buffer for extra channels if downmixing */
if (avctx->channels < full_channels) {
ret = av_samples_get_buffer_size(NULL, full_channels - channels,
frame->nb_samples,
avctx->sample_fmt, 0);
if (ret < 0)
return ret;
av_fast_malloc(&s->extra_channels_buffer,
&s->extra_channels_buffer_size, ret);
if (!s->extra_channels_buffer)
return AVERROR(ENOMEM);
ret = av_samples_fill_arrays((uint8_t **) s->extra_channels, NULL,
s->extra_channels_buffer,
full_channels - channels,
frame->nb_samples, avctx->sample_fmt, 0);
if (ret < 0)
return ret;
}
/* filter to get final output */
for (i = 0; i < (s->sample_blocks / SAMPLES_PER_SUBBAND); i++) {
int ch;
unsigned block = upsample ? 512 : 256;
for (ch = 0; ch < channels; ch++)
s->samples_chanptr[ch] = samples_flt[ch] + i * block;
for (; ch < full_channels; ch++)
s->samples_chanptr[ch] = s->extra_channels[ch - channels] + i * block;
dca_filter_channels(s, i, upsample);
/* If this was marked as a DTS-ES stream we need to subtract back- */
/* channel from SL & SR to remove matrixed back-channel signal */
if ((s->source_pcm_res & 1) && s->xch_present) {
float *back_chan = s->samples_chanptr[s->channel_order_tab[s->xch_base_channel]];
float *lt_chan = s->samples_chanptr[s->channel_order_tab[s->xch_base_channel - 2]];
float *rt_chan = s->samples_chanptr[s->channel_order_tab[s->xch_base_channel - 1]];
s->fdsp->vector_fmac_scalar(lt_chan, back_chan, -M_SQRT1_2, 256);
s->fdsp->vector_fmac_scalar(rt_chan, back_chan, -M_SQRT1_2, 256);
}
/* If stream contains XXCH, we might need to undo an embedded downmix */
if (s->xxch_dmix_embedded) {
/* Loop over channel sets in turn */
ch = num_core_channels;
for (chset = 0; chset < s->xxch_chset; chset++) {
endch = ch + s->xxch_chset_nch[chset];
mask = s->xxch_dmix_embedded;
/* undo downmix */
for (j = ch; j < endch; j++) {
if (mask & (1 << j)) { /* this channel has been mixed-out */
src_chan = s->samples_chanptr[s->channel_order_tab[j]];
for (k = 0; k < endch; k++) {
achan = s->channel_order_tab[k];
scale = s->xxch_dmix_coeff[j][k];
if (scale != 0.0) {
dst_chan = s->samples_chanptr[achan];
s->fdsp->vector_fmac_scalar(dst_chan, src_chan,
-scale, 256);
}
}
}
}
/* if a downmix has been embedded then undo the pre-scaling */
if ((mask & (1 << ch)) && s->xxch_dmix_sf[chset] != 1.0f) {
scale = s->xxch_dmix_sf[chset];
for (j = 0; j < ch; j++) {
src_chan = s->samples_chanptr[s->channel_order_tab[j]];
for (k = 0; k < 256; k++)
src_chan[k] *= scale;
}
/* LFE channel is always part of core, scale if it exists */
if (s->lfe) {
src_chan = s->samples_chanptr[s->lfe_index];
for (k = 0; k < 256; k++)
src_chan[k] *= scale;
}
}
ch = endch;
}
}
}
/* update lfe history */
lfe_samples = 2 * s->lfe * (s->sample_blocks / SAMPLES_PER_SUBBAND);
for (i = 0; i < 2 * s->lfe * 4; i++)
s->lfe_data[i] = s->lfe_data[i + lfe_samples];
if (s->exss_ext_mask & DCA_EXT_EXSS_XLL) {
ret = ff_dca_xll_decode_audio(s, frame);
if (ret < 0)
return ret;
}
/* AVMatrixEncoding
*
* DCA_STEREO_TOTAL (Lt/Rt) is equivalent to Dolby Surround */
ret = ff_side_data_update_matrix_encoding(frame,
(s->output & ~DCA_LFE) == DCA_STEREO_TOTAL ?
AV_MATRIX_ENCODING_DOLBY : AV_MATRIX_ENCODING_NONE);
if (ret < 0)
return ret;
if ( avctx->profile != FF_PROFILE_DTS_HD_MA
&& avctx->profile != FF_PROFILE_DTS_HD_HRA)
avctx->bit_rate = s->bit_rate;
*got_frame_ptr = 1;
return buf_size;
}
/**
* DCA initialization
*
* @param avctx pointer to the AVCodecContext
*/
static av_cold int dca_decode_init(AVCodecContext *avctx)
{
DCAContext *s = avctx->priv_data;
s->avctx = avctx;
dca_init_vlcs();
s->fdsp = avpriv_float_dsp_alloc(avctx->flags & AV_CODEC_FLAG_BITEXACT);
if (!s->fdsp)
return AVERROR(ENOMEM);
ff_mdct_init(&s->imdct, 6, 1, 1.0);
ff_synth_filter_init(&s->synth);
ff_dcadsp_init(&s->dcadsp);
ff_fmt_convert_init(&s->fmt_conv, avctx);
avctx->sample_fmt = AV_SAMPLE_FMT_FLTP;
/* allow downmixing to stereo */
if (avctx->channels > 2 &&
avctx->request_channel_layout == AV_CH_LAYOUT_STEREO)
avctx->channels = 2;
return 0;
}
static av_cold int dca_decode_end(AVCodecContext *avctx)
{
DCAContext *s = avctx->priv_data;
ff_mdct_end(&s->imdct);
av_freep(&s->extra_channels_buffer);
av_freep(&s->fdsp);
av_freep(&s->xll_sample_buf);
av_freep(&s->qmf64_table);
return 0;
}
static const AVOption options[] = {
{ "disable_xch", "disable decoding of the XCh extension", offsetof(DCAContext, xch_disable), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM },
{ "disable_xll", "disable decoding of the XLL extension", offsetof(DCAContext, xll_disable), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM },
{ NULL },
};
static const AVClass dca_decoder_class = {
.class_name = "DCA decoder",
.item_name = av_default_item_name,
.option = options,
.version = LIBAVUTIL_VERSION_INT,
.category = AV_CLASS_CATEGORY_DECODER,
};
AVCodec ff_dca_decoder = {
.name = "dca",
.long_name = NULL_IF_CONFIG_SMALL("DCA (DTS Coherent Acoustics)"),
.type = AVMEDIA_TYPE_AUDIO,
.id = AV_CODEC_ID_DTS,
.priv_data_size = sizeof(DCAContext),
.init = dca_decode_init,
.decode = dca_decode_frame,
.close = dca_decode_end,
.capabilities = AV_CODEC_CAP_CHANNEL_CONF | AV_CODEC_CAP_DR1,
.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP,
AV_SAMPLE_FMT_NONE },
.profiles = NULL_IF_CONFIG_SMALL(ff_dca_profiles),
.priv_class = &dca_decoder_class,
};
/*
* Copyright (c) 2004 Gildas Bazin
* Copyright (c) 2010 Mans Rullgard <mans@mansr.com>
*
* 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 "config.h"
#include "libavutil/attributes.h"
#include "libavutil/intreadwrite.h"
#include "dcadsp.h"
#include "dcamath.h"
static void decode_hf_c(int32_t dst[DCA_SUBBANDS][SAMPLES_PER_SUBBAND],
const int32_t vq_num[DCA_SUBBANDS],
const int8_t hf_vq[1024][32], intptr_t vq_offset,
int32_t scale[DCA_SUBBANDS][2],
intptr_t start, intptr_t end)
{
int i, j;
for (j = start; j < end; j++) {
const int8_t *ptr = &hf_vq[vq_num[j]][vq_offset];
for (i = 0; i < 8; i++)
dst[j][i] = ptr[i] * scale[j][0] + 8 >> 4;
}
}
static inline void dca_lfe_fir(float *out, const float *in, const float *coefs,
int decifactor)
{
float *out2 = out + 2 * decifactor - 1;
int num_coeffs = 256 / decifactor;
int j, k;
/* One decimated sample generates 2*decifactor interpolated ones */
for (k = 0; k < decifactor; k++) {
float v0 = 0.0;
float v1 = 0.0;
for (j = 0; j < num_coeffs; j++, coefs++) {
v0 += in[-j] * *coefs;
v1 += in[j + 1 - num_coeffs] * *coefs;
}
*out++ = v0;
*out2-- = v1;
}
}
static void dca_qmf_32_subbands(float samples_in[DCA_SUBBANDS][SAMPLES_PER_SUBBAND], int sb_act,
SynthFilterContext *synth, FFTContext *imdct,
float synth_buf_ptr[512],
int *synth_buf_offset, float synth_buf2[32],
const float window[512], float *samples_out,
float raXin[32], float scale)
{
int i;
int subindex;
for (i = sb_act; i < 32; i++)
raXin[i] = 0.0;
/* Reconstructed channel sample index */
for (subindex = 0; subindex < 8; subindex++) {
/* Load in one sample from each subband and clear inactive subbands */
for (i = 0; i < sb_act; i++) {
unsigned sign = (i - 1) & 2;
uint32_t v = AV_RN32A(&samples_in[i][subindex]) ^ sign << 30;
AV_WN32A(&raXin[i], v);
}
synth->synth_filter_float(imdct, synth_buf_ptr, synth_buf_offset,
synth_buf2, window, samples_out, raXin,
scale);
samples_out += 32;
}
}
static void dequantize_c(int32_t *samples, uint32_t step_size, uint32_t scale)
{
int64_t step = (int64_t)step_size * scale;
int shift, i;
int32_t step_scale;
if (step > (1 << 23))
shift = av_log2(step >> 23) + 1;
else
shift = 0;
step_scale = (int32_t)(step >> shift);
for (i = 0; i < SAMPLES_PER_SUBBAND; i++)
samples[i] = dca_clip23(dca_norm((int64_t)samples[i] * step_scale, 22 - shift));
}
static void dca_lfe_fir0_c(float *out, const float *in, const float *coefs)
{
dca_lfe_fir(out, in, coefs, 32);
}
static void dca_lfe_fir1_c(float *out, const float *in, const float *coefs)
{
dca_lfe_fir(out, in, coefs, 64);
}
av_cold void ff_dcadsp_init(DCADSPContext *s)
{
s->lfe_fir[0] = dca_lfe_fir0_c;
s->lfe_fir[1] = dca_lfe_fir1_c;
s->qmf_32_subbands = dca_qmf_32_subbands;
s->decode_hf = decode_hf_c;
s->dequantize = dequantize_c;
if (ARCH_AARCH64)
ff_dcadsp_init_aarch64(s);
if (ARCH_ARM)
ff_dcadsp_init_arm(s);
if (ARCH_X86)
ff_dcadsp_init_x86(s);
}
/*
* 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 "avfft.h"
#include "synth_filter.h"
#define DCA_SUBBANDS_X96K 64
#define DCA_SUBBANDS 64
#define SAMPLES_PER_SUBBAND 8 // number of samples per subband per subsubframe
typedef struct DCADSPContext {
void (*lfe_fir[2])(float *out, const float *in, const float *coefs);
void (*qmf_32_subbands)(float samples_in[DCA_SUBBANDS][SAMPLES_PER_SUBBAND], int sb_act,
SynthFilterContext *synth, FFTContext *imdct,
float synth_buf_ptr[512],
int *synth_buf_offset, float synth_buf2[32],
const float window[512], float *samples_out,
float raXin[32], float scale);
void (*decode_hf)(int32_t dst[DCA_SUBBANDS][SAMPLES_PER_SUBBAND],
const int32_t vq_num[DCA_SUBBANDS],
const int8_t hf_vq[1024][32], intptr_t vq_offset,
int32_t scale[DCA_SUBBANDS][2],
intptr_t start, intptr_t end);
void (*dequantize)(int32_t *samples, uint32_t step_size, uint32_t scale);
} DCADSPContext;
void ff_dcadsp_init(DCADSPContext *s);
void ff_dcadsp_init_aarch64(DCADSPContext *s);
void ff_dcadsp_init_arm(DCADSPContext *s);
void ff_dcadsp_init_x86(DCADSPContext *s);
#endif /* AVCODEC_DCADSP_H */
/*
* 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_DCAMATH_H
#define AVCODEC_DCAMATH_H
#include "libavutil/common.h"
// clip a signed integer into the (-2^23), (2^23-1) range
static inline int dca_clip23(int a)
{
return av_clip_intp2(a, 23);
}
static inline int32_t dca_norm(int64_t a, int bits)
{
if (bits > 0)
return (int32_t)((a + (INT64_C(1) << (bits - 1))) >> bits);
else
return (int32_t)a;
}
static inline int64_t dca_round(int64_t a, int bits)
{
if (bits > 0)
return (a + (INT64_C(1) << (bits - 1))) & ~((INT64_C(1) << bits) - 1);
else
return a;
}
#endif /* AVCODEC_DCAMATH_H */
......@@ -44,8 +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/dcadsp_init.o \
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
......@@ -133,8 +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/dcadsp.o \
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
......
;******************************************************************************
;* SSE-optimized functions for the DCA decoder
;* Copyright (C) 2012-2014 Christophe Gisquet <christophe.gisquet@gmail.com>
;*
;* 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/x86/x86util.asm"
SECTION_RODATA
pf_inv16: times 4 dd 0x3D800000 ; 1/16
SECTION .text
; %1=v0/v1 %2=in1 %3=in2
%macro FIR_LOOP 2-3
.loop%1:
%define va m1
%define vb m2
%if %1
%define OFFSET 0
%else
%define OFFSET NUM_COEF*count
%endif
; for v0, incrementing and for v1, decrementing
mova va, [cf0q + OFFSET]
mova vb, [cf0q + OFFSET + 4*NUM_COEF]
%if %0 == 3
mova m4, [cf0q + OFFSET + mmsize]
mova m0, [cf0q + OFFSET + 4*NUM_COEF + mmsize]
%endif
mulps va, %2
mulps vb, %2
%if %0 == 3
%if cpuflag(fma3)
fmaddps va, m4, %3, va
fmaddps vb, m0, %3, vb
%else
mulps m4, %3
mulps m0, %3
addps va, m4
addps vb, m0
%endif
%endif
; va = va1 va2 va3 va4
; vb = vb1 vb2 vb3 vb4
%if %1
SWAP va, vb
%endif
mova m4, va
unpcklps va, vb ; va3 vb3 va4 vb4
unpckhps m4, vb ; va1 vb1 va2 vb2
addps m4, va ; va1+3 vb1+3 va2+4 vb2+4
movhlps vb, m4 ; va1+3 vb1+3
addps vb, m4 ; va0..4 vb0..4
movlps [outq + count], vb
%if %1
sub cf0q, 8*NUM_COEF
%endif
add count, 8
jl .loop%1
%endmacro
; void dca_lfe_fir(float *out, float *in, float *coefs)
%macro DCA_LFE_FIR 1
cglobal dca_lfe_fir%1, 3,3,6-%1, out, in, cf0
%define IN1 m3
%define IN2 m5
%define count inq
%define NUM_COEF 4*(2-%1)
%define NUM_OUT 32*(%1+1)
movu IN1, [inq + 4 - 1*mmsize]
shufps IN1, IN1, q0123
%if %1 == 0
movu IN2, [inq + 4 - 2*mmsize]
shufps IN2, IN2, q0123
%endif
mov count, -4*NUM_OUT
add cf0q, 4*NUM_COEF*NUM_OUT
add outq, 4*NUM_OUT
; compute v0 first
%if %1 == 0
FIR_LOOP 0, IN1, IN2
%else
FIR_LOOP 0, IN1
%endif
shufps IN1, IN1, q0123
mov count, -4*NUM_OUT
; cf1 already correctly positioned
add outq, 4*NUM_OUT ; outq now at out2
sub cf0q, 8*NUM_COEF
%if %1 == 0
shufps IN2, IN2, q0123
FIR_LOOP 1, IN2, IN1
%else
FIR_LOOP 1, IN1
%endif
RET
%endmacro
INIT_XMM sse
DCA_LFE_FIR 0
DCA_LFE_FIR 1
%if HAVE_FMA3_EXTERNAL
INIT_XMM fma3
DCA_LFE_FIR 0
%endif
/*
* Copyright (c) 2012-2014 Christophe Gisquet <christophe.gisquet@gmail.com>
*
* 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/attributes.h"
#include "libavutil/cpu.h"
#include "libavutil/x86/cpu.h"
#include "libavcodec/dcadsp.h"
void ff_dca_lfe_fir0_sse(float *out, const float *in, const float *coefs);
void ff_dca_lfe_fir1_sse(float *out, const float *in, const float *coefs);
void ff_dca_lfe_fir0_fma3(float *out, const float *in, const float *coefs);
av_cold void ff_dcadsp_init_x86(DCADSPContext *s)
{
int cpu_flags = av_get_cpu_flags();
if (EXTERNAL_SSE(cpu_flags)) {
s->lfe_fir[0] = ff_dca_lfe_fir0_sse;
s->lfe_fir[1] = ff_dca_lfe_fir1_sse;
}
if (EXTERNAL_FMA3(cpu_flags)) {
s->lfe_fir[0] = ff_dca_lfe_fir0_fma3;
}
}
# libavcodec tests
AVCODECOBJS-$(CONFIG_ALAC_DECODER) += alacdsp.o
AVCODECOBJS-$(CONFIG_BSWAPDSP) += bswapdsp.o
AVCODECOBJS-$(CONFIG_DCA_DECODER) += dcadsp.o 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
......
......@@ -71,10 +71,9 @@ static const struct {
#if CONFIG_BSWAPDSP
{ "bswapdsp", checkasm_check_bswapdsp },
#endif
#if CONFIG_DCA_DECODER
{ "dcadsp", checkasm_check_dcadsp },
/* #if CONFIG_DCA_DECODER
{ "synth_filter", checkasm_check_synth_filter },
#endif
#endif*/
#if CONFIG_FLACDSP
{ "flacdsp", checkasm_check_flacdsp },
#endif
......
......@@ -32,7 +32,6 @@
void checkasm_check_alacdsp(void);
void checkasm_check_bswapdsp(void);
void checkasm_check_dcadsp(void);
void checkasm_check_flacdsp(void);
void checkasm_check_fmtconvert(void);
void checkasm_check_h264pred(void);
......
/*
* Copyright (c) 2015 Janne Grunau
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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 <math.h>
#include <string.h>
#include <stdlib.h>
#include "libavutil/internal.h"
#include "libavutil/intfloat.h"
#include "libavcodec/dca.h"
#include "libavcodec/dcadsp.h"
#include "libavcodec/dcadata.h"
#include "checkasm.h"
#define randomize_lfe_fir(size) \
do { \
int i; \
for (i = 0; i < size; i++) { \
float f = (float)rnd() / (UINT_MAX >> 1) - 1.0f; \
in[i] = f; \
} \
for (i = 0; i < 256; i++) { \
float f = (float)rnd() / (UINT_MAX >> 1) - 1.0f; \
coeffs[i] = f; \
} \
} while (0)
#define check_lfe_fir(decifactor, eps) \
do { \
LOCAL_ALIGNED_16(float, in, [256 / decifactor]); \
LOCAL_ALIGNED_16(float, out0, [decifactor * 2]); \
LOCAL_ALIGNED_16(float, out1, [decifactor * 2]); \
LOCAL_ALIGNED_16(float, coeffs, [256]); \
int i; \
const float * in_ptr = in + (256 / decifactor) - 1; \
declare_func(void, float *out, const float *in, const float *coeffs); \
/* repeat the test several times */ \
for (i = 0; i < 32; i++) { \
int j; \
memset(out0, 0, sizeof(*out0) * 2 * decifactor); \
memset(out1, 0xFF, sizeof(*out1) * 2 * decifactor); \
randomize_lfe_fir(256 / decifactor); \
call_ref(out0, in_ptr, coeffs); \
call_new(out1, in_ptr, coeffs); \
for (j = 0; j < 2 * decifactor; j++) { \
if (!float_near_abs_eps(out0[j], out1[j], eps)) { \
if (0) { \
union av_intfloat32 x, y; x.f = out0[j]; y.f = out1[j]; \
fprintf(stderr, "%3d: %11g (0x%08x); %11g (0x%08x)\n", \
j, x.f, x.i, y.f, y.i); \
} \
fail(); \
break; \
} \
} \
bench_new(out1, in_ptr, coeffs); \
} \
} while (0)
void checkasm_check_dcadsp(void)
{
DCADSPContext c;
ff_dcadsp_init(&c);
/* values are limited to {-8, 8} so absolute epsilon is good enough */
if (check_func(c.lfe_fir[0], "dca_lfe_fir0"))
check_lfe_fir(32, 1.0e-6f);
if (check_func(c.lfe_fir[1], "dca_lfe_fir1"))
check_lfe_fir(64, 1.0e-6f);
report("dcadsp");
}
......@@ -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
......
......@@ -21,12 +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_DCA-$(CONFIG_DTS_DEMUXER) += fate-dca-xll
fate-dca-xll: CMD = pcm -disable_xll 0 -i $(TARGET_SAMPLES)/dts/master_audio_7.1_24bit.dts
fate-dca-xll: CMP = oneoff
fate-dca-xll: REF = $(SAMPLES)/dts/master_audio_7.1_24bit_2.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
......@@ -36,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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment