Libav
|
00001 /* 00002 * Alpha optimized DSP utils 00003 * Copyright (c) 2002 Falk Hueffner <falk@debian.org> 00004 * 00005 * This file is part of FFmpeg. 00006 * 00007 * FFmpeg is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * FFmpeg is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with FFmpeg; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00020 */ 00021 00022 #include "libavcodec/dsputil.h" 00023 #include "libavcodec/mpegvideo.h" 00024 #include "asm.h" 00025 00026 static void dct_unquantize_h263_axp(DCTELEM *block, int n_coeffs, 00027 uint64_t qscale, uint64_t qadd) 00028 { 00029 uint64_t qmul = qscale << 1; 00030 uint64_t correction = WORD_VEC(qmul * 255 >> 8); 00031 int i; 00032 00033 qadd = WORD_VEC(qadd); 00034 00035 for(i = 0; i <= n_coeffs; block += 4, i += 4) { 00036 uint64_t levels, negmask, zeros, add, sub; 00037 00038 levels = ldq(block); 00039 if (levels == 0) 00040 continue; 00041 00042 #ifdef __alpha_max__ 00043 /* I don't think the speed difference justifies runtime 00044 detection. */ 00045 negmask = maxsw4(levels, -1); /* negative -> ffff (-1) */ 00046 negmask = minsw4(negmask, 0); /* positive -> 0000 (0) */ 00047 #else 00048 negmask = cmpbge(WORD_VEC(0x7fff), levels); 00049 negmask &= (negmask >> 1) | (1 << 7); 00050 negmask = zap(-1, negmask); 00051 #endif 00052 00053 zeros = cmpbge(0, levels); 00054 zeros &= zeros >> 1; 00055 /* zeros |= zeros << 1 is not needed since qadd <= 255, so 00056 zapping the lower byte suffices. */ 00057 00058 levels *= qmul; 00059 levels -= correction & (negmask << 16); 00060 00061 add = qadd & ~negmask; 00062 sub = qadd & negmask; 00063 /* Set qadd to 0 for levels == 0. */ 00064 add = zap(add, zeros); 00065 levels += add; 00066 levels -= sub; 00067 00068 stq(levels, block); 00069 } 00070 } 00071 00072 static void dct_unquantize_h263_intra_axp(MpegEncContext *s, DCTELEM *block, 00073 int n, int qscale) 00074 { 00075 int n_coeffs; 00076 uint64_t qadd; 00077 DCTELEM block0 = block[0]; 00078 00079 if (!s->h263_aic) { 00080 if (n < 4) 00081 block0 *= s->y_dc_scale; 00082 else 00083 block0 *= s->c_dc_scale; 00084 qadd = (qscale - 1) | 1; 00085 } else { 00086 qadd = 0; 00087 } 00088 00089 if(s->ac_pred) 00090 n_coeffs = 63; 00091 else 00092 n_coeffs = s->inter_scantable.raster_end[s->block_last_index[n]]; 00093 00094 dct_unquantize_h263_axp(block, n_coeffs, qscale, qadd); 00095 00096 block[0] = block0; 00097 } 00098 00099 static void dct_unquantize_h263_inter_axp(MpegEncContext *s, DCTELEM *block, 00100 int n, int qscale) 00101 { 00102 int n_coeffs = s->inter_scantable.raster_end[s->block_last_index[n]]; 00103 dct_unquantize_h263_axp(block, n_coeffs, qscale, (qscale - 1) | 1); 00104 } 00105 00106 void MPV_common_init_axp(MpegEncContext *s) 00107 { 00108 s->dct_unquantize_h263_intra = dct_unquantize_h263_intra_axp; 00109 s->dct_unquantize_h263_inter = dct_unquantize_h263_inter_axp; 00110 }