diff options
Diffstat (limited to 'libavcodec/alpha/mpegvideo_alpha.c')
-rw-r--r-- | libavcodec/alpha/mpegvideo_alpha.c | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/libavcodec/alpha/mpegvideo_alpha.c b/libavcodec/alpha/mpegvideo_alpha.c new file mode 100644 index 0000000000..126fe264a1 --- /dev/null +++ b/libavcodec/alpha/mpegvideo_alpha.c @@ -0,0 +1,110 @@ +/* + * Alpha optimized DSP utils + * Copyright (c) 2002 Falk Hueffner <falk@debian.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/attributes.h" +#include "libavcodec/mpegvideo.h" +#include "asm.h" + +static void dct_unquantize_h263_axp(int16_t *block, int n_coeffs, + uint64_t qscale, uint64_t qadd) +{ + uint64_t qmul = qscale << 1; + uint64_t correction = WORD_VEC(qmul * 255 >> 8); + int i; + + qadd = WORD_VEC(qadd); + + for(i = 0; i <= n_coeffs; block += 4, i += 4) { + uint64_t levels, negmask, zeros, add, sub; + + levels = ldq(block); + if (levels == 0) + continue; + +#ifdef __alpha_max__ + /* I don't think the speed difference justifies runtime + detection. */ + negmask = maxsw4(levels, -1); /* negative -> ffff (-1) */ + negmask = minsw4(negmask, 0); /* positive -> 0000 (0) */ +#else + negmask = cmpbge(WORD_VEC(0x7fff), levels); + negmask &= (negmask >> 1) | (1 << 7); + negmask = zap(-1, negmask); +#endif + + zeros = cmpbge(0, levels); + zeros &= zeros >> 1; + /* zeros |= zeros << 1 is not needed since qadd <= 255, so + zapping the lower byte suffices. */ + + levels *= qmul; + levels -= correction & (negmask << 16); + + add = qadd & ~negmask; + sub = qadd & negmask; + /* Set qadd to 0 for levels == 0. */ + add = zap(add, zeros); + levels += add; + levels -= sub; + + stq(levels, block); + } +} + +static void dct_unquantize_h263_intra_axp(MpegEncContext *s, int16_t *block, + int n, int qscale) +{ + int n_coeffs; + uint64_t qadd; + int16_t block0 = block[0]; + + if (!s->h263_aic) { + if (n < 4) + block0 *= s->y_dc_scale; + else + block0 *= s->c_dc_scale; + qadd = (qscale - 1) | 1; + } else { + qadd = 0; + } + + if(s->ac_pred) + n_coeffs = 63; + else + n_coeffs = s->inter_scantable.raster_end[s->block_last_index[n]]; + + dct_unquantize_h263_axp(block, n_coeffs, qscale, qadd); + + block[0] = block0; +} + +static void dct_unquantize_h263_inter_axp(MpegEncContext *s, int16_t *block, + int n, int qscale) +{ + int n_coeffs = s->inter_scantable.raster_end[s->block_last_index[n]]; + dct_unquantize_h263_axp(block, n_coeffs, qscale, (qscale - 1) | 1); +} + +av_cold void ff_mpv_common_init_axp(MpegEncContext *s) +{ + s->dct_unquantize_h263_intra = dct_unquantize_h263_intra_axp; + s->dct_unquantize_h263_inter = dct_unquantize_h263_inter_axp; +} |