mirror of https://github.com/FFmpeg/FFmpeg.git
parent
5c026e6637
commit
41ae2b03a5
10 changed files with 626 additions and 531 deletions
@ -0,0 +1,174 @@ |
||||
/*
|
||||
* AAC decoder |
||||
* Copyright (c) 2005-2006 Oded Shimon ( ods15 ods15 dyndns org ) |
||||
* Copyright (c) 2006-2007 Maxim Gavrilov ( maxim.gavrilov gmail com ) |
||||
* Copyright (c) 2008-2013 Alex Converse <alex.converse@gmail.com> |
||||
* |
||||
* AAC LATM decoder |
||||
* Copyright (c) 2008-2010 Paul Kendall <paul@kcbbs.gen.nz> |
||||
* Copyright (c) 2010 Janne Grunau <janne-libav@jannau.net> |
||||
* |
||||
* AAC decoder fixed-point implementation |
||||
* Copyright (c) 2013 |
||||
* MIPS Technologies, Inc., California. |
||||
* |
||||
* 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_AAC_AACDEC_FIXED_DEQUANT_H |
||||
#define AVCODEC_AAC_AACDEC_FIXED_DEQUANT_H |
||||
|
||||
#include "aacdec_tab.h" |
||||
|
||||
static void inline vector_pow43(int *coefs, int len) |
||||
{ |
||||
int i, coef; |
||||
|
||||
for (i=0; i<len; i++) { |
||||
coef = coefs[i]; |
||||
if (coef < 0) |
||||
coef = -(int)ff_cbrt_tab_fixed[(-coef) & 8191]; |
||||
else |
||||
coef = (int)ff_cbrt_tab_fixed[ coef & 8191]; |
||||
coefs[i] = coef; |
||||
} |
||||
} |
||||
|
||||
/* 2^0, 2^0.25, 2^0.5, 2^0.75 */ |
||||
static const int exp2tab[4] = { |
||||
Q31(1.0000000000/2), Q31(1.1892071150/2), |
||||
Q31(1.4142135624/2), Q31(1.6817928305/2) |
||||
}; |
||||
|
||||
static void inline subband_scale(int *dst, int *src, int scale, |
||||
int offset, int len, void *log_context) |
||||
{ |
||||
int ssign = scale < 0 ? -1 : 1; |
||||
int s = FFABS(scale); |
||||
unsigned int round; |
||||
int i, out, c = exp2tab[s & 3]; |
||||
|
||||
s = offset - (s >> 2); |
||||
|
||||
if (s > 31) { |
||||
for (i=0; i<len; i++) { |
||||
dst[i] = 0; |
||||
} |
||||
} else if (s > 0) { |
||||
round = 1 << (s-1); |
||||
for (i=0; i<len; i++) { |
||||
out = (int)(((int64_t)src[i] * c) >> 32); |
||||
dst[i] = ((int)(out+round) >> s) * ssign; |
||||
} |
||||
} else if (s > -32) { |
||||
s = s + 32; |
||||
round = 1U << (s-1); |
||||
for (i=0; i<len; i++) { |
||||
out = (int)((int64_t)((int64_t)src[i] * c + round) >> s); |
||||
dst[i] = out * (unsigned)ssign; |
||||
} |
||||
} else { |
||||
av_log(log_context, AV_LOG_ERROR, "Overflow in subband_scale()\n"); |
||||
} |
||||
} |
||||
|
||||
static void noise_scale(int *coefs, int scale, int band_energy, int len) |
||||
{ |
||||
int s = -scale; |
||||
unsigned int round; |
||||
int i, out, c = exp2tab[s & 3]; |
||||
int nlz = 0; |
||||
|
||||
av_assert0(s >= 0); |
||||
while (band_energy > 0x7fff) { |
||||
band_energy >>= 1; |
||||
nlz++; |
||||
} |
||||
c /= band_energy; |
||||
s = 21 + nlz - (s >> 2); |
||||
|
||||
if (s > 31) { |
||||
for (i=0; i<len; i++) { |
||||
coefs[i] = 0; |
||||
} |
||||
} else if (s >= 0) { |
||||
round = s ? 1 << (s-1) : 0; |
||||
for (i=0; i<len; i++) { |
||||
out = (int)(((int64_t)coefs[i] * c) >> 32); |
||||
coefs[i] = -((int)(out+round) >> s); |
||||
} |
||||
} |
||||
else { |
||||
s = s + 32; |
||||
if (s > 0) { |
||||
round = 1 << (s-1); |
||||
for (i=0; i<len; i++) { |
||||
out = (int)((int64_t)((int64_t)coefs[i] * c + round) >> s); |
||||
coefs[i] = -out; |
||||
} |
||||
} else { |
||||
for (i=0; i<len; i++) |
||||
coefs[i] = -(int64_t)coefs[i] * c * (1 << -s); |
||||
} |
||||
} |
||||
} |
||||
|
||||
static inline int *DEC_SPAIR(int *dst, unsigned idx) |
||||
{ |
||||
dst[0] = (idx & 15) - 4; |
||||
dst[1] = (idx >> 4 & 15) - 4; |
||||
|
||||
return dst + 2; |
||||
} |
||||
|
||||
static inline int *DEC_SQUAD(int *dst, unsigned idx) |
||||
{ |
||||
dst[0] = (idx & 3) - 1; |
||||
dst[1] = (idx >> 2 & 3) - 1; |
||||
dst[2] = (idx >> 4 & 3) - 1; |
||||
dst[3] = (idx >> 6 & 3) - 1; |
||||
|
||||
return dst + 4; |
||||
} |
||||
|
||||
static inline int *DEC_UPAIR(int *dst, unsigned idx, unsigned sign) |
||||
{ |
||||
dst[0] = (idx & 15) * (1 - (sign & 0xFFFFFFFE)); |
||||
dst[1] = (idx >> 4 & 15) * (1 - ((sign & 1) * 2)); |
||||
|
||||
return dst + 2; |
||||
} |
||||
|
||||
static inline int *DEC_UQUAD(int *dst, unsigned idx, unsigned sign) |
||||
{ |
||||
unsigned nz = idx >> 12; |
||||
|
||||
dst[0] = (idx & 3) * (1 + (((int)sign >> 31) * 2)); |
||||
sign <<= nz & 1; |
||||
nz >>= 1; |
||||
dst[1] = (idx >> 2 & 3) * (1 + (((int)sign >> 31) * 2)); |
||||
sign <<= nz & 1; |
||||
nz >>= 1; |
||||
dst[2] = (idx >> 4 & 3) * (1 + (((int)sign >> 31) * 2)); |
||||
sign <<= nz & 1; |
||||
nz >>= 1; |
||||
dst[3] = (idx >> 6 & 3) * (1 + (((int)sign >> 31) * 2)); |
||||
|
||||
return dst + 4; |
||||
} |
||||
|
||||
#endif /* AVCODEC_AAC_AACDEC_FIXED_DEQUANT_H */ |
@ -0,0 +1,354 @@ |
||||
/*
|
||||
* AAC decoder |
||||
* Copyright (c) 2005-2006 Oded Shimon ( ods15 ods15 dyndns org ) |
||||
* Copyright (c) 2006-2007 Maxim Gavrilov ( maxim.gavrilov gmail com ) |
||||
* Copyright (c) 2008-2013 Alex Converse <alex.converse@gmail.com> |
||||
* |
||||
* AAC LATM decoder |
||||
* Copyright (c) 2008-2010 Paul Kendall <paul@kcbbs.gen.nz> |
||||
* Copyright (c) 2010 Janne Grunau <janne-libav@jannau.net> |
||||
* |
||||
* AAC decoder fixed-point implementation |
||||
* Copyright (c) 2013 |
||||
* MIPS Technologies, Inc., California. |
||||
* |
||||
* 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 |
||||
*/ |
||||
|
||||
/**
|
||||
* linear congruential pseudorandom number generator |
||||
* |
||||
* @param previous_val pointer to the current state of the generator |
||||
* |
||||
* @return Returns a 32-bit pseudorandom integer |
||||
*/ |
||||
static av_always_inline int lcg_random(unsigned previous_val) |
||||
{ |
||||
union { unsigned u; int s; } v = { previous_val * 1664525u + 1013904223 }; |
||||
return v.s; |
||||
} |
||||
|
||||
/**
|
||||
* Decode spectral data; reference: table 4.50. |
||||
* Dequantize and scale spectral data; reference: 4.6.3.3. |
||||
* |
||||
* @param coef array of dequantized, scaled spectral data |
||||
* @param sf array of scalefactors or intensity stereo positions |
||||
* @param pulse_present set if pulses are present |
||||
* @param pulse pointer to pulse data struct |
||||
* @param band_type array of the used band type |
||||
* |
||||
* @return Returns error status. 0 - OK, !0 - error |
||||
*/ |
||||
static int AAC_RENAME(decode_spectrum_and_dequant)(AACDecContext *ac, |
||||
GetBitContext *gb, |
||||
const Pulse *pulse, |
||||
SingleChannelElement *sce) |
||||
{ |
||||
int i, k, g, idx = 0; |
||||
INTFLOAT *coef = sce->AAC_RENAME(coeffs); |
||||
IndividualChannelStream *ics = &sce->ics; |
||||
const int c = 1024 / ics->num_windows; |
||||
const uint16_t *offsets = ics->swb_offset; |
||||
const INTFLOAT *sf = sce->AAC_RENAME(sf); |
||||
const enum BandType *band_type = sce->band_type; |
||||
INTFLOAT *coef_base = coef; |
||||
|
||||
for (g = 0; g < ics->num_windows; g++) |
||||
memset(coef + g * 128 + offsets[ics->max_sfb], 0, |
||||
sizeof(INTFLOAT) * (c - offsets[ics->max_sfb])); |
||||
|
||||
for (g = 0; g < ics->num_window_groups; g++) { |
||||
unsigned g_len = ics->group_len[g]; |
||||
|
||||
for (i = 0; i < ics->max_sfb; i++, idx++) { |
||||
const unsigned cbt_m1 = band_type[idx] - 1; |
||||
INTFLOAT *cfo = coef + offsets[i]; |
||||
int off_len = offsets[i + 1] - offsets[i]; |
||||
int group; |
||||
|
||||
if (cbt_m1 >= INTENSITY_BT2 - 1) { |
||||
for (group = 0; group < (AAC_SIGNE)g_len; group++, cfo+=128) { |
||||
memset(cfo, 0, off_len * sizeof(*cfo)); |
||||
} |
||||
} else if (cbt_m1 == NOISE_BT - 1) { |
||||
for (group = 0; group < (AAC_SIGNE)g_len; group++, cfo+=128) { |
||||
INTFLOAT band_energy; |
||||
#if USE_FIXED |
||||
for (k = 0; k < off_len; k++) { |
||||
ac->random_state = lcg_random(ac->random_state); |
||||
cfo[k] = ac->random_state >> 3; |
||||
} |
||||
|
||||
band_energy = ac->fdsp->scalarproduct_fixed(cfo, cfo, off_len); |
||||
band_energy = fixed_sqrt(band_energy, 31); |
||||
noise_scale(cfo, sf[idx], band_energy, off_len); |
||||
#else |
||||
float scale; |
||||
|
||||
for (k = 0; k < off_len; k++) { |
||||
ac->random_state = lcg_random(ac->random_state); |
||||
cfo[k] = ac->random_state; |
||||
} |
||||
|
||||
band_energy = ac->fdsp->scalarproduct_float(cfo, cfo, off_len); |
||||
scale = sf[idx] / sqrtf(band_energy); |
||||
ac->fdsp->vector_fmul_scalar(cfo, cfo, scale, off_len); |
||||
#endif /* USE_FIXED */ |
||||
} |
||||
} else { |
||||
#if !USE_FIXED |
||||
const float *vq = ff_aac_codebook_vector_vals[cbt_m1]; |
||||
#endif /* !USE_FIXED */ |
||||
const VLCElem *vlc_tab = ff_vlc_spectral[cbt_m1]; |
||||
OPEN_READER(re, gb); |
||||
|
||||
switch (cbt_m1 >> 1) { |
||||
case 0: |
||||
for (group = 0; group < (AAC_SIGNE)g_len; group++, cfo+=128) { |
||||
INTFLOAT *cf = cfo; |
||||
int len = off_len; |
||||
|
||||
do { |
||||
int code; |
||||
unsigned cb_idx; |
||||
|
||||
UPDATE_CACHE(re, gb); |
||||
GET_VLC(code, re, gb, vlc_tab, 8, 2); |
||||
cb_idx = code; |
||||
#if USE_FIXED |
||||
cf = DEC_SQUAD(cf, cb_idx); |
||||
#else |
||||
cf = VMUL4(cf, vq, cb_idx, sf + idx); |
||||
#endif /* USE_FIXED */ |
||||
} while (len -= 4); |
||||
} |
||||
break; |
||||
|
||||
case 1: |
||||
for (group = 0; group < (AAC_SIGNE)g_len; group++, cfo+=128) { |
||||
INTFLOAT *cf = cfo; |
||||
int len = off_len; |
||||
|
||||
do { |
||||
int code; |
||||
unsigned nnz; |
||||
unsigned cb_idx; |
||||
uint32_t bits; |
||||
|
||||
UPDATE_CACHE(re, gb); |
||||
GET_VLC(code, re, gb, vlc_tab, 8, 2); |
||||
cb_idx = code; |
||||
nnz = cb_idx >> 8 & 15; |
||||
bits = nnz ? GET_CACHE(re, gb) : 0; |
||||
LAST_SKIP_BITS(re, gb, nnz); |
||||
#if USE_FIXED |
||||
cf = DEC_UQUAD(cf, cb_idx, bits); |
||||
#else |
||||
cf = VMUL4S(cf, vq, cb_idx, bits, sf + idx); |
||||
#endif /* USE_FIXED */ |
||||
} while (len -= 4); |
||||
} |
||||
break; |
||||
|
||||
case 2: |
||||
for (group = 0; group < (AAC_SIGNE)g_len; group++, cfo+=128) { |
||||
INTFLOAT *cf = cfo; |
||||
int len = off_len; |
||||
|
||||
do { |
||||
int code; |
||||
unsigned cb_idx; |
||||
|
||||
UPDATE_CACHE(re, gb); |
||||
GET_VLC(code, re, gb, vlc_tab, 8, 2); |
||||
cb_idx = code; |
||||
#if USE_FIXED |
||||
cf = DEC_SPAIR(cf, cb_idx); |
||||
#else |
||||
cf = VMUL2(cf, vq, cb_idx, sf + idx); |
||||
#endif /* USE_FIXED */ |
||||
} while (len -= 2); |
||||
} |
||||
break; |
||||
|
||||
case 3: |
||||
case 4: |
||||
for (group = 0; group < (AAC_SIGNE)g_len; group++, cfo+=128) { |
||||
INTFLOAT *cf = cfo; |
||||
int len = off_len; |
||||
|
||||
do { |
||||
int code; |
||||
unsigned nnz; |
||||
unsigned cb_idx; |
||||
unsigned sign; |
||||
|
||||
UPDATE_CACHE(re, gb); |
||||
GET_VLC(code, re, gb, vlc_tab, 8, 2); |
||||
cb_idx = code; |
||||
nnz = cb_idx >> 8 & 15; |
||||
sign = nnz ? SHOW_UBITS(re, gb, nnz) << (cb_idx >> 12) : 0; |
||||
LAST_SKIP_BITS(re, gb, nnz); |
||||
#if USE_FIXED |
||||
cf = DEC_UPAIR(cf, cb_idx, sign); |
||||
#else |
||||
cf = VMUL2S(cf, vq, cb_idx, sign, sf + idx); |
||||
#endif /* USE_FIXED */ |
||||
} while (len -= 2); |
||||
} |
||||
break; |
||||
|
||||
default: |
||||
for (group = 0; group < (AAC_SIGNE)g_len; group++, cfo+=128) { |
||||
#if USE_FIXED |
||||
int *icf = cfo; |
||||
int v; |
||||
#else |
||||
float *cf = cfo; |
||||
uint32_t *icf = (uint32_t *) cf; |
||||
#endif /* USE_FIXED */ |
||||
int len = off_len; |
||||
|
||||
do { |
||||
int code; |
||||
unsigned nzt, nnz; |
||||
unsigned cb_idx; |
||||
uint32_t bits; |
||||
int j; |
||||
|
||||
UPDATE_CACHE(re, gb); |
||||
GET_VLC(code, re, gb, vlc_tab, 8, 2); |
||||
cb_idx = code; |
||||
|
||||
if (cb_idx == 0x0000) { |
||||
*icf++ = 0; |
||||
*icf++ = 0; |
||||
continue; |
||||
} |
||||
|
||||
nnz = cb_idx >> 12; |
||||
nzt = cb_idx >> 8; |
||||
bits = SHOW_UBITS(re, gb, nnz) << (32-nnz); |
||||
LAST_SKIP_BITS(re, gb, nnz); |
||||
|
||||
for (j = 0; j < 2; j++) { |
||||
if (nzt & 1<<j) { |
||||
uint32_t b; |
||||
int n; |
||||
/* The total length of escape_sequence must be < 22 bits according
|
||||
to the specification (i.e. max is 111111110xxxxxxxxxxxx). */ |
||||
UPDATE_CACHE(re, gb); |
||||
b = GET_CACHE(re, gb); |
||||
b = 31 - av_log2(~b); |
||||
|
||||
if (b > 8) { |
||||
av_log(ac->avctx, AV_LOG_ERROR, "error in spectral data, ESC overflow\n"); |
||||
return AVERROR_INVALIDDATA; |
||||
} |
||||
|
||||
SKIP_BITS(re, gb, b + 1); |
||||
b += 4; |
||||
n = (1 << b) + SHOW_UBITS(re, gb, b); |
||||
LAST_SKIP_BITS(re, gb, b); |
||||
#if USE_FIXED |
||||
v = n; |
||||
if (bits & 1U<<31) |
||||
v = -v; |
||||
*icf++ = v; |
||||
#else |
||||
*icf++ = ff_cbrt_tab[n] | (bits & 1U<<31); |
||||
#endif /* USE_FIXED */ |
||||
bits <<= 1; |
||||
} else { |
||||
#if USE_FIXED |
||||
v = cb_idx & 15; |
||||
if (bits & 1U<<31) |
||||
v = -v; |
||||
*icf++ = v; |
||||
#else |
||||
unsigned v = ((const uint32_t*)vq)[cb_idx & 15]; |
||||
*icf++ = (bits & 1U<<31) | v; |
||||
#endif /* USE_FIXED */ |
||||
bits <<= !!v; |
||||
} |
||||
cb_idx >>= 4; |
||||
} |
||||
} while (len -= 2); |
||||
#if !USE_FIXED |
||||
ac->fdsp->vector_fmul_scalar(cfo, cfo, sf[idx], off_len); |
||||
#endif /* !USE_FIXED */ |
||||
} |
||||
} |
||||
|
||||
CLOSE_READER(re, gb); |
||||
} |
||||
} |
||||
coef += g_len << 7; |
||||
} |
||||
|
||||
if (pulse) { |
||||
idx = 0; |
||||
for (i = 0; i < pulse->num_pulse; i++) { |
||||
INTFLOAT co = coef_base[ pulse->pos[i] ]; |
||||
while (offsets[idx + 1] <= pulse->pos[i]) |
||||
idx++; |
||||
if (band_type[idx] != NOISE_BT && sf[idx]) { |
||||
INTFLOAT ico = -pulse->amp[i]; |
||||
#if USE_FIXED |
||||
if (co) { |
||||
ico = co + (co > 0 ? -ico : ico); |
||||
} |
||||
coef_base[ pulse->pos[i] ] = ico; |
||||
#else |
||||
if (co) { |
||||
co /= sf[idx]; |
||||
ico = co / sqrtf(sqrtf(fabsf(co))) + (co > 0 ? -ico : ico); |
||||
} |
||||
coef_base[ pulse->pos[i] ] = cbrtf(fabsf(ico)) * ico * sf[idx]; |
||||
#endif /* USE_FIXED */ |
||||
} |
||||
} |
||||
} |
||||
#if USE_FIXED |
||||
coef = coef_base; |
||||
idx = 0; |
||||
for (g = 0; g < ics->num_window_groups; g++) { |
||||
unsigned g_len = ics->group_len[g]; |
||||
|
||||
for (i = 0; i < ics->max_sfb; i++, idx++) { |
||||
const unsigned cbt_m1 = band_type[idx] - 1; |
||||
int *cfo = coef + offsets[i]; |
||||
int off_len = offsets[i + 1] - offsets[i]; |
||||
int group; |
||||
|
||||
if (cbt_m1 < NOISE_BT - 1) { |
||||
for (group = 0; group < (int)g_len; group++, cfo+=128) { |
||||
vector_pow43(cfo, off_len); |
||||
subband_scale(cfo, cfo, sf[idx], 34, off_len, ac->avctx); |
||||
} |
||||
} |
||||
} |
||||
coef += g_len << 7; |
||||
} |
||||
#endif /* USE_FIXED */ |
||||
return 0; |
||||
} |
||||
|
||||
const AACDecProc AAC_RENAME(aac_proc) = { |
||||
.decode_spectrum_and_dequant = AAC_RENAME(decode_spectrum_and_dequant), |
||||
}; |
Loading…
Reference in new issue