mirror of https://github.com/FFmpeg/FFmpeg.git
Remove all files and functions which are not going to be reused, and disable all functions and FATE tests temporarily which will be.pull/174/head
parent
b552f3afa2
commit
4608996772
29 changed files with 17 additions and 5064 deletions
@ -1,39 +0,0 @@ |
|||||||
/*
|
|
||||||
* 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; |
|
||||||
} |
|
||||||
} |
|
@ -1,109 +0,0 @@ |
|||||||
/* |
|
||||||
* 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 |
|
@ -1,53 +0,0 @@ |
|||||||
/*
|
|
||||||
* 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; |
|
||||||
} |
|
||||||
} |
|
@ -1,64 +0,0 @@ |
|||||||
/* |
|
||||||
* 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 |
|
@ -1,476 +0,0 @@ |
|||||||
/* |
|
||||||
* 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 |
|
@ -1,373 +0,0 @@ |
|||||||
/*
|
|
||||||
* 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); |
|
||||||
} |
|
||||||
} |
|
@ -1,747 +0,0 @@ |
|||||||
/*
|
|
||||||
* 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 = ¶m_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; |
|
||||||
} |
|
File diff suppressed because it is too large
Load Diff
@ -1,134 +0,0 @@ |
|||||||
/*
|
|
||||||
* 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); |
|
||||||
} |
|
@ -1,51 +0,0 @@ |
|||||||
/*
|
|
||||||
* 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 */ |
|
@ -1,47 +0,0 @@ |
|||||||
/*
|
|
||||||
* 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 */ |
|
@ -1,123 +0,0 @@ |
|||||||
;****************************************************************************** |
|
||||||
;* 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 |
|
@ -1,42 +0,0 @@ |
|||||||
/*
|
|
||||||
* 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; |
|
||||||
} |
|
||||||
} |
|
@ -1,92 +0,0 @@ |
|||||||
/*
|
|
||||||
* 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"); |
|
||||||
} |
|
Loading…
Reference in new issue