Performance improvements: quant_bands: with: 681 decicycles in quant_bands, 8388453 runs, 155 skips without: 1190 decicycles in quant_bands, 8388386 runs, 222 skips Around 42% for the function Twoloop coder: abs_pow34: with/without: 7.82s/8.17s Around 4% for the entire encoder Both: with/without: 7.15s/8.17s Around 12% for the entire encoder Fast coder: abs_pow34: with/without: 3.40s/3.77s Around 10% for the entire encoder Both: with/without: 3.02s/3.77s Around 20% faster for the entire encoder Signed-off-by: Rostislav Pehlivanov <atomnuker@gmail.com> Tested-by: Michael Niedermayer <michael@niedermayer.cc> Reviewed-by: James Almer <jamrial@gmail.com>tags/n3.2
@@ -88,7 +88,7 @@ static void encode_window_bands_info(AACEncContext *s, SingleChannelElement *sce | |||||
float next_minrd = INFINITY; | float next_minrd = INFINITY; | ||||
int next_mincb = 0; | int next_mincb = 0; | ||||
abs_pow34_v(s->scoefs, sce->coeffs, 1024); | |||||
s->abs_pow34(s->scoefs, sce->coeffs, 1024); | |||||
start = win*128; | start = win*128; | ||||
for (cb = 0; cb < CB_TOT_ALL; cb++) { | for (cb = 0; cb < CB_TOT_ALL; cb++) { | ||||
path[0][cb].cost = 0.0f; | path[0][cb].cost = 0.0f; | ||||
@@ -299,7 +299,7 @@ static void search_for_quantizers_anmr(AVCodecContext *avctx, AACEncContext *s, | |||||
} | } | ||||
} | } | ||||
idx = 1; | idx = 1; | ||||
abs_pow34_v(s->scoefs, sce->coeffs, 1024); | |||||
s->abs_pow34(s->scoefs, sce->coeffs, 1024); | |||||
for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) { | for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) { | ||||
start = w*128; | start = w*128; | ||||
for (g = 0; g < sce->ics.num_swb; g++) { | for (g = 0; g < sce->ics.num_swb; g++) { | ||||
@@ -446,7 +446,7 @@ static void search_for_quantizers_fast(AVCodecContext *avctx, AACEncContext *s, | |||||
if (!allz) | if (!allz) | ||||
return; | return; | ||||
abs_pow34_v(s->scoefs, sce->coeffs, 1024); | |||||
s->abs_pow34(s->scoefs, sce->coeffs, 1024); | |||||
ff_quantize_band_cost_cache_init(s); | ff_quantize_band_cost_cache_init(s); | ||||
for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) { | for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) { | ||||
@@ -652,8 +652,8 @@ static void search_for_pns(AACEncContext *s, AVCodecContext *avctx, SingleChanne | |||||
s->fdsp->vector_fmul_scalar(PNS, PNS, scale, sce->ics.swb_sizes[g]); | s->fdsp->vector_fmul_scalar(PNS, PNS, scale, sce->ics.swb_sizes[g]); | ||||
pns_senergy = s->fdsp->scalarproduct_float(PNS, PNS, sce->ics.swb_sizes[g]); | pns_senergy = s->fdsp->scalarproduct_float(PNS, PNS, sce->ics.swb_sizes[g]); | ||||
pns_energy += pns_senergy; | pns_energy += pns_senergy; | ||||
abs_pow34_v(NOR34, &sce->coeffs[start_c], sce->ics.swb_sizes[g]); | |||||
abs_pow34_v(PNS34, PNS, sce->ics.swb_sizes[g]); | |||||
s->abs_pow34(NOR34, &sce->coeffs[start_c], sce->ics.swb_sizes[g]); | |||||
s->abs_pow34(PNS34, PNS, sce->ics.swb_sizes[g]); | |||||
dist1 += quantize_band_cost(s, &sce->coeffs[start_c], | dist1 += quantize_band_cost(s, &sce->coeffs[start_c], | ||||
NOR34, | NOR34, | ||||
sce->ics.swb_sizes[g], | sce->ics.swb_sizes[g], | ||||
@@ -757,8 +757,9 @@ static void search_for_ms(AACEncContext *s, ChannelElement *cpe) | |||||
{ | { | ||||
int start = 0, i, w, w2, g, sid_sf_boost, prev_mid, prev_side; | int start = 0, i, w, w2, g, sid_sf_boost, prev_mid, prev_side; | ||||
uint8_t nextband0[128], nextband1[128]; | uint8_t nextband0[128], nextband1[128]; | ||||
float M[128], S[128]; | |||||
float *L34 = s->scoefs, *R34 = s->scoefs + 128, *M34 = s->scoefs + 128*2, *S34 = s->scoefs + 128*3; | |||||
float *M = s->scoefs + 128*0, *S = s->scoefs + 128*1; | |||||
float *L34 = s->scoefs + 128*2, *R34 = s->scoefs + 128*3; | |||||
float *M34 = s->scoefs + 128*4, *S34 = s->scoefs + 128*5; | |||||
const float lambda = s->lambda; | const float lambda = s->lambda; | ||||
const float mslambda = FFMIN(1.0f, lambda / 120.f); | const float mslambda = FFMIN(1.0f, lambda / 120.f); | ||||
SingleChannelElement *sce0 = &cpe->ch[0]; | SingleChannelElement *sce0 = &cpe->ch[0]; | ||||
@@ -789,8 +790,8 @@ static void search_for_ms(AACEncContext *s, ChannelElement *cpe) | |||||
S[i] = M[i] | S[i] = M[i] | ||||
- sce1->coeffs[start+(w+w2)*128+i]; | - sce1->coeffs[start+(w+w2)*128+i]; | ||||
} | } | ||||
abs_pow34_v(M34, M, sce0->ics.swb_sizes[g]); | |||||
abs_pow34_v(S34, S, sce0->ics.swb_sizes[g]); | |||||
s->abs_pow34(M34, M, sce0->ics.swb_sizes[g]); | |||||
s->abs_pow34(S34, S, sce0->ics.swb_sizes[g]); | |||||
for (i = 0; i < sce0->ics.swb_sizes[g]; i++ ) { | for (i = 0; i < sce0->ics.swb_sizes[g]; i++ ) { | ||||
Mmax = FFMAX(Mmax, M34[i]); | Mmax = FFMAX(Mmax, M34[i]); | ||||
Smax = FFMAX(Smax, S34[i]); | Smax = FFMAX(Smax, S34[i]); | ||||
@@ -833,10 +834,10 @@ static void search_for_ms(AACEncContext *s, ChannelElement *cpe) | |||||
- sce1->coeffs[start+(w+w2)*128+i]; | - sce1->coeffs[start+(w+w2)*128+i]; | ||||
} | } | ||||
abs_pow34_v(L34, sce0->coeffs+start+(w+w2)*128, sce0->ics.swb_sizes[g]); | |||||
abs_pow34_v(R34, sce1->coeffs+start+(w+w2)*128, sce0->ics.swb_sizes[g]); | |||||
abs_pow34_v(M34, M, sce0->ics.swb_sizes[g]); | |||||
abs_pow34_v(S34, S, sce0->ics.swb_sizes[g]); | |||||
s->abs_pow34(L34, sce0->coeffs+start+(w+w2)*128, sce0->ics.swb_sizes[g]); | |||||
s->abs_pow34(R34, sce1->coeffs+start+(w+w2)*128, sce0->ics.swb_sizes[g]); | |||||
s->abs_pow34(M34, M, sce0->ics.swb_sizes[g]); | |||||
s->abs_pow34(S34, S, sce0->ics.swb_sizes[g]); | |||||
dist1 += quantize_band_cost(s, &sce0->coeffs[start + (w+w2)*128], | dist1 += quantize_band_cost(s, &sce0->coeffs[start + (w+w2)*128], | ||||
L34, | L34, | ||||
sce0->ics.swb_sizes[g], | sce0->ics.swb_sizes[g], | ||||
@@ -70,7 +70,7 @@ static void codebook_trellis_rate(AACEncContext *s, SingleChannelElement *sce, | |||||
float next_minbits = INFINITY; | float next_minbits = INFINITY; | ||||
int next_mincb = 0; | int next_mincb = 0; | ||||
abs_pow34_v(s->scoefs, sce->coeffs, 1024); | |||||
s->abs_pow34(s->scoefs, sce->coeffs, 1024); | |||||
start = win*128; | start = win*128; | ||||
for (cb = 0; cb < CB_TOT_ALL; cb++) { | for (cb = 0; cb < CB_TOT_ALL; cb++) { | ||||
path[0][cb].cost = run_bits+4; | path[0][cb].cost = run_bits+4; | ||||
@@ -291,7 +291,7 @@ static void search_for_quantizers_twoloop(AVCodecContext *avctx, | |||||
if (!allz) | if (!allz) | ||||
return; | return; | ||||
abs_pow34_v(s->scoefs, sce->coeffs, 1024); | |||||
s->abs_pow34(s->scoefs, sce->coeffs, 1024); | |||||
ff_quantize_band_cost_cache_init(s); | ff_quantize_band_cost_cache_init(s); | ||||
for (i = 0; i < sizeof(minsf) / sizeof(minsf[0]); ++i) | for (i = 0; i < sizeof(minsf) / sizeof(minsf[0]); ++i) | ||||
@@ -1033,6 +1033,12 @@ static av_cold int aac_encode_init(AVCodecContext *avctx) | |||||
ff_lpc_init(&s->lpc, 2*avctx->frame_size, TNS_MAX_ORDER, FF_LPC_TYPE_LEVINSON); | ff_lpc_init(&s->lpc, 2*avctx->frame_size, TNS_MAX_ORDER, FF_LPC_TYPE_LEVINSON); | ||||
s->random_state = 0x1f2e3d4c; | s->random_state = 0x1f2e3d4c; | ||||
s->abs_pow34 = abs_pow34_v; | |||||
s->quant_bands = quantize_bands; | |||||
if (ARCH_X86) | |||||
ff_aac_dsp_init_x86(s); | |||||
if (HAVE_MIPSDSP) | if (HAVE_MIPSDSP) | ||||
ff_aac_coder_init_mips(s); | ff_aac_coder_init_mips(s); | ||||
@@ -127,11 +127,17 @@ typedef struct AACEncContext { | |||||
uint16_t quantize_band_cost_cache_generation; | uint16_t quantize_band_cost_cache_generation; | ||||
AACQuantizeBandCostCacheEntry quantize_band_cost_cache[256][128]; ///< memoization area for quantize_band_cost | AACQuantizeBandCostCacheEntry quantize_band_cost_cache[256][128]; ///< memoization area for quantize_band_cost | ||||
void (*abs_pow34)(float *out, const float *in, const int size); | |||||
void (*quant_bands)(int *out, const float *in, const float *scaled, | |||||
int size, int is_signed, int maxval, const float Q34, | |||||
const float rounding); | |||||
struct { | struct { | ||||
float *samples; | float *samples; | ||||
} buffer; | } buffer; | ||||
} AACEncContext; | } AACEncContext; | ||||
void ff_aac_dsp_init_x86(AACEncContext *s); | |||||
void ff_aac_coder_init_mips(AACEncContext *c); | void ff_aac_coder_init_mips(AACEncContext *c); | ||||
void ff_quantize_band_cost_cache_init(struct AACEncContext *s); | void ff_quantize_band_cost_cache_init(struct AACEncContext *s); | ||||
@@ -59,9 +59,9 @@ struct AACISError ff_aac_is_encoding_err(AACEncContext *s, ChannelElement *cpe, | |||||
float minthr = FFMIN(band0->threshold, band1->threshold); | float minthr = FFMIN(band0->threshold, band1->threshold); | ||||
for (i = 0; i < sce0->ics.swb_sizes[g]; i++) | for (i = 0; i < sce0->ics.swb_sizes[g]; i++) | ||||
IS[i] = (L[start+(w+w2)*128+i] + phase*R[start+(w+w2)*128+i])*sqrt(ener0/ener01); | IS[i] = (L[start+(w+w2)*128+i] + phase*R[start+(w+w2)*128+i])*sqrt(ener0/ener01); | ||||
abs_pow34_v(L34, &L[start+(w+w2)*128], sce0->ics.swb_sizes[g]); | |||||
abs_pow34_v(R34, &R[start+(w+w2)*128], sce0->ics.swb_sizes[g]); | |||||
abs_pow34_v(I34, IS, sce0->ics.swb_sizes[g]); | |||||
s->abs_pow34(L34, &L[start+(w+w2)*128], sce0->ics.swb_sizes[g]); | |||||
s->abs_pow34(R34, &R[start+(w+w2)*128], sce0->ics.swb_sizes[g]); | |||||
s->abs_pow34(I34, IS, sce0->ics.swb_sizes[g]); | |||||
maxval = find_max_val(1, sce0->ics.swb_sizes[g], I34); | maxval = find_max_val(1, sce0->ics.swb_sizes[g], I34); | ||||
is_band_type = find_min_book(maxval, is_sf_idx); | is_band_type = find_min_book(maxval, is_sf_idx); | ||||
dist1 += quantize_band_cost(s, &L[start + (w+w2)*128], L34, | dist1 += quantize_band_cost(s, &L[start + (w+w2)*128], L34, | ||||
@@ -190,8 +190,8 @@ void ff_aac_search_for_ltp(AACEncContext *s, SingleChannelElement *sce, | |||||
FFPsyBand *band = &s->psy.ch[s->cur_channel].psy_bands[(w+w2)*16+g]; | FFPsyBand *band = &s->psy.ch[s->cur_channel].psy_bands[(w+w2)*16+g]; | ||||
for (i = 0; i < sce->ics.swb_sizes[g]; i++) | for (i = 0; i < sce->ics.swb_sizes[g]; i++) | ||||
PCD[i] = sce->coeffs[start+(w+w2)*128+i] - sce->lcoeffs[start+(w+w2)*128+i]; | PCD[i] = sce->coeffs[start+(w+w2)*128+i] - sce->lcoeffs[start+(w+w2)*128+i]; | ||||
abs_pow34_v(C34, &sce->coeffs[start+(w+w2)*128], sce->ics.swb_sizes[g]); | |||||
abs_pow34_v(PCD34, PCD, sce->ics.swb_sizes[g]); | |||||
s->abs_pow34(C34, &sce->coeffs[start+(w+w2)*128], sce->ics.swb_sizes[g]); | |||||
s->abs_pow34(PCD34, PCD, sce->ics.swb_sizes[g]); | |||||
dist1 += quantize_band_cost(s, &sce->coeffs[start+(w+w2)*128], C34, sce->ics.swb_sizes[g], | dist1 += quantize_band_cost(s, &sce->coeffs[start+(w+w2)*128], C34, sce->ics.swb_sizes[g], | ||||
sce->sf_idx[(w+w2)*16+g], sce->band_type[(w+w2)*16+g], | sce->sf_idx[(w+w2)*16+g], sce->band_type[(w+w2)*16+g], | ||||
s->lambda/band->threshold, INFINITY, &bits_tmp1, NULL, 0); | s->lambda/band->threshold, INFINITY, &bits_tmp1, NULL, 0); | ||||
@@ -270,7 +270,7 @@ void ff_aac_search_for_pred(AACEncContext *s, SingleChannelElement *sce) | |||||
continue; | continue; | ||||
/* Normal coefficients */ | /* Normal coefficients */ | ||||
abs_pow34_v(O34, &sce->coeffs[start_coef], num_coeffs); | |||||
s->abs_pow34(O34, &sce->coeffs[start_coef], num_coeffs); | |||||
dist1 = quantize_and_encode_band_cost(s, NULL, &sce->coeffs[start_coef], NULL, | dist1 = quantize_and_encode_band_cost(s, NULL, &sce->coeffs[start_coef], NULL, | ||||
O34, num_coeffs, sce->sf_idx[sfb], | O34, num_coeffs, sce->sf_idx[sfb], | ||||
cb_n, s->lambda / band->threshold, INFINITY, &cost1, NULL, 0); | cb_n, s->lambda / band->threshold, INFINITY, &cost1, NULL, 0); | ||||
@@ -279,7 +279,7 @@ void ff_aac_search_for_pred(AACEncContext *s, SingleChannelElement *sce) | |||||
/* Encoded coefficients - needed for #bits, band type and quant. error */ | /* Encoded coefficients - needed for #bits, band type and quant. error */ | ||||
for (i = 0; i < num_coeffs; i++) | for (i = 0; i < num_coeffs; i++) | ||||
SENT[i] = sce->coeffs[start_coef + i] - sce->prcoeffs[start_coef + i]; | SENT[i] = sce->coeffs[start_coef + i] - sce->prcoeffs[start_coef + i]; | ||||
abs_pow34_v(S34, SENT, num_coeffs); | |||||
s->abs_pow34(S34, SENT, num_coeffs); | |||||
if (cb_n < RESERVED_BT) | if (cb_n < RESERVED_BT) | ||||
cb_p = av_clip(find_min_book(find_max_val(1, num_coeffs, S34), sce->sf_idx[sfb]), cb_min, cb_max); | cb_p = av_clip(find_min_book(find_max_val(1, num_coeffs, S34), sce->sf_idx[sfb]), cb_min, cb_max); | ||||
else | else | ||||
@@ -291,7 +291,7 @@ void ff_aac_search_for_pred(AACEncContext *s, SingleChannelElement *sce) | |||||
/* Reconstructed coefficients - needed for distortion measurements */ | /* Reconstructed coefficients - needed for distortion measurements */ | ||||
for (i = 0; i < num_coeffs; i++) | for (i = 0; i < num_coeffs; i++) | ||||
sce->prcoeffs[start_coef + i] += QERR[i] != 0.0f ? (sce->prcoeffs[start_coef + i] - QERR[i]) : 0.0f; | sce->prcoeffs[start_coef + i] += QERR[i] != 0.0f ? (sce->prcoeffs[start_coef + i] - QERR[i]) : 0.0f; | ||||
abs_pow34_v(P34, &sce->prcoeffs[start_coef], num_coeffs); | |||||
s->abs_pow34(P34, &sce->prcoeffs[start_coef], num_coeffs); | |||||
if (cb_n < RESERVED_BT) | if (cb_n < RESERVED_BT) | ||||
cb_p = av_clip(find_min_book(find_max_val(1, num_coeffs, P34), sce->sf_idx[sfb]), cb_min, cb_max); | cb_p = av_clip(find_min_book(find_max_val(1, num_coeffs, P34), sce->sf_idx[sfb]), cb_min, cb_max); | ||||
else | else | ||||
@@ -74,10 +74,10 @@ static av_always_inline float quantize_and_encode_band_cost_template( | |||||
return cost * lambda; | return cost * lambda; | ||||
} | } | ||||
if (!scaled) { | if (!scaled) { | ||||
abs_pow34_v(s->scoefs, in, size); | |||||
s->abs_pow34(s->scoefs, in, size); | |||||
scaled = s->scoefs; | scaled = s->scoefs; | ||||
} | } | ||||
quantize_bands(s->qcoefs, in, scaled, size, Q34, !BT_UNSIGNED, aac_cb_maxval[cb], ROUNDING); | |||||
s->quant_bands(s->qcoefs, in, scaled, size, !BT_UNSIGNED, aac_cb_maxval[cb], Q34, ROUNDING); | |||||
if (BT_UNSIGNED) { | if (BT_UNSIGNED) { | ||||
off = 0; | off = 0; | ||||
} else { | } else { | ||||
@@ -63,7 +63,7 @@ static inline int quant(float coef, const float Q, const float rounding) | |||||
} | } | ||||
static inline void quantize_bands(int *out, const float *in, const float *scaled, | static inline void quantize_bands(int *out, const float *in, const float *scaled, | ||||
int size, float Q34, int is_signed, int maxval, | |||||
int size, int is_signed, int maxval, const float Q34, | |||||
const float rounding) | const float rounding) | ||||
{ | { | ||||
int i; | int i; | ||||
@@ -42,6 +42,7 @@ OBJS-$(CONFIG_XMM_CLOBBER_TEST) += x86/w64xmmtest.o | |||||
# decoders/encoders | # decoders/encoders | ||||
OBJS-$(CONFIG_AAC_DECODER) += x86/aacpsdsp_init.o \ | OBJS-$(CONFIG_AAC_DECODER) += x86/aacpsdsp_init.o \ | ||||
x86/sbrdsp_init.o | x86/sbrdsp_init.o | ||||
OBJS-$(CONFIG_AAC_ENCODER) += x86/aacencdsp_init.o | |||||
OBJS-$(CONFIG_ADPCM_G722_DECODER) += x86/g722dsp_init.o | OBJS-$(CONFIG_ADPCM_G722_DECODER) += x86/g722dsp_init.o | ||||
OBJS-$(CONFIG_ADPCM_G722_ENCODER) += x86/g722dsp_init.o | OBJS-$(CONFIG_ADPCM_G722_ENCODER) += x86/g722dsp_init.o | ||||
OBJS-$(CONFIG_ALAC_DECODER) += x86/alacdsp_init.o | OBJS-$(CONFIG_ALAC_DECODER) += x86/alacdsp_init.o | ||||
@@ -132,6 +133,7 @@ YASM-OBJS-$(CONFIG_VP8DSP) += x86/vp8dsp.o \ | |||||
# decoders/encoders | # decoders/encoders | ||||
YASM-OBJS-$(CONFIG_AAC_DECODER) += x86/aacpsdsp.o \ | YASM-OBJS-$(CONFIG_AAC_DECODER) += x86/aacpsdsp.o \ | ||||
x86/sbrdsp.o | x86/sbrdsp.o | ||||
YASM-OBJS-$(CONFIG_AAC_ENCODER) += x86/aacencdsp.o | |||||
YASM-OBJS-$(CONFIG_ADPCM_G722_DECODER) += x86/g722dsp.o | YASM-OBJS-$(CONFIG_ADPCM_G722_DECODER) += x86/g722dsp.o | ||||
YASM-OBJS-$(CONFIG_ADPCM_G722_ENCODER) += x86/g722dsp.o | YASM-OBJS-$(CONFIG_ADPCM_G722_ENCODER) += x86/g722dsp.o | ||||
YASM-OBJS-$(CONFIG_ALAC_DECODER) += x86/alacdsp.o | YASM-OBJS-$(CONFIG_ALAC_DECODER) += x86/alacdsp.o | ||||
@@ -0,0 +1,86 @@ | |||||
;****************************************************************************** | |||||
;* SIMD optimized AAC encoder DSP functions | |||||
;* | |||||
;* Copyright (C) 2016 Rostislav Pehlivanov <atomnuker@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 | |||||
float_abs_mask: times 4 dd 0x7fffffff | |||||
SECTION .text | |||||
;******************************************************************* | |||||
;void ff_abs_pow34(float *out, const float *in, const int size); | |||||
;******************************************************************* | |||||
INIT_XMM sse | |||||
cglobal abs_pow34, 3, 3, 3, out, in, size | |||||
mova m2, [float_abs_mask] | |||||
shl sizeq, 2 | |||||
add inq, sizeq | |||||
add outq, sizeq | |||||
neg sizeq | |||||
.loop: | |||||
andps m0, m2, [inq+sizeq] | |||||
sqrtps m1, m0 | |||||
mulps m0, m1 | |||||
sqrtps m0, m0 | |||||
mova [outq+sizeq], m0 | |||||
add sizeq, mmsize | |||||
jl .loop | |||||
RET | |||||
;******************************************************************* | |||||
;void ff_aac_quantize_bands(int *out, const float *in, const float *scaled, | |||||
; int size, int is_signed, int maxval, const float Q34, | |||||
; const float rounding) | |||||
;******************************************************************* | |||||
INIT_XMM sse2 | |||||
cglobal aac_quantize_bands, 5, 5, 6, out, in, scaled, size, is_signed, maxval, Q34, rounding | |||||
%if UNIX64 == 0 | |||||
movss m0, Q34m | |||||
movss m1, roundingm | |||||
cvtsi2ss m3, dword maxvalm | |||||
%else | |||||
cvtsi2ss m3, maxvald | |||||
%endif | |||||
shufps m0, m0, 0 | |||||
shufps m1, m1, 0 | |||||
shufps m3, m3, 0 | |||||
shl is_signedd, 31 | |||||
movd m4, is_signedd | |||||
shufps m4, m4, 0 | |||||
shl sized, 2 | |||||
add inq, sizeq | |||||
add outq, sizeq | |||||
add scaledq, sizeq | |||||
neg sizeq | |||||
.loop: | |||||
mulps m2, m0, [scaledq+sizeq] | |||||
addps m2, m1 | |||||
minps m2, m3 | |||||
andps m5, m4, [inq+sizeq] | |||||
orps m2, m5 | |||||
cvttps2dq m2, m2 | |||||
mova [outq+sizeq], m2 | |||||
add sizeq, mmsize | |||||
jl .loop | |||||
RET |
@@ -0,0 +1,43 @@ | |||||
/* | |||||
* AAC encoder assembly optimizations | |||||
* Copyright (C) 2016 Rostislav Pehlivanov <atomnuker@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 "config.h" | |||||
#include "libavutil/float_dsp.h" | |||||
#include "libavutil/x86/cpu.h" | |||||
#include "libavcodec/aacenc.h" | |||||
void ff_abs_pow34_sse(float *out, const float *in, const int size); | |||||
void ff_aac_quantize_bands_sse2(int *out, const float *in, const float *scaled, | |||||
int size, int is_signed, int maxval, const float Q34, | |||||
const float rounding); | |||||
av_cold void ff_aac_dsp_init_x86(AACEncContext *s) | |||||
{ | |||||
int cpu_flags = av_get_cpu_flags(); | |||||
if (EXTERNAL_SSE(cpu_flags)) | |||||
s->abs_pow34 = ff_abs_pow34_sse; | |||||
if (EXTERNAL_SSE2(cpu_flags)) | |||||
s->quant_bands = ff_aac_quantize_bands_sse2; | |||||
} |