nengel@2: /* nengel@2: * DSP utils nengel@2: * Copyright (c) 2000, 2001 Fabrice Bellard nengel@2: * Copyright (c) 2002-2004 Michael Niedermayer nengel@2: * nengel@2: * gmc & q-pel & 32/64 bit based MC by Michael Niedermayer nengel@2: * nengel@2: * This file is part of FFmpeg. nengel@2: * nengel@2: * FFmpeg is free software; you can redistribute it and/or nengel@2: * modify it under the terms of the GNU Lesser General Public nengel@2: * License as published by the Free Software Foundation; either nengel@2: * version 2.1 of the License, or (at your option) any later version. nengel@2: * nengel@2: * FFmpeg is distributed in the hope that it will be useful, nengel@2: * but WITHOUT ANY WARRANTY; without even the implied warranty of nengel@2: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU nengel@2: * Lesser General Public License for more details. nengel@2: * nengel@2: * You should have received a copy of the GNU Lesser General Public nengel@2: * License along with FFmpeg; if not, write to the Free Software nengel@2: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA nengel@2: */ nengel@2: nengel@2: /** nengel@2: * @file nengel@2: * DSP utils nengel@2: */ nengel@2: nengel@2: #include "libavutil/log.h" nengel@2: #include "dsputil.h" nengel@2: #include "simple_idct.h" nengel@2: #include "mathops.h" nengel@2: #include "config.h" nengel@2: nengel@2: uint8_t ff_cropTbl[256 + 2 * MAX_NEG_CROP] = {0, }; nengel@2: uint32_t ff_squareTbl[512] = {0, }; nengel@2: nengel@2: const uint8_t ff_zigzag_direct[64] = { nengel@2: 0, 1, 8, 16, 9, 2, 3, 10, nengel@2: 17, 24, 32, 25, 18, 11, 4, 5, nengel@2: 12, 19, 26, 33, 40, 48, 41, 34, nengel@2: 27, 20, 13, 6, 7, 14, 21, 28, nengel@2: 35, 42, 49, 56, 57, 50, 43, 36, nengel@2: 29, 22, 15, 23, 30, 37, 44, 51, nengel@2: 58, 59, 52, 45, 38, 31, 39, 46, nengel@2: 53, 60, 61, 54, 47, 55, 62, 63 nengel@2: }; nengel@2: nengel@2: nengel@2: #define PIXOP2(OPNAME, OP) \ nengel@2: static void OPNAME ## _pixels2_c(uint8_t *block, const uint8_t *pixels, int line_size, int h){\ nengel@2: int i;\ nengel@2: for(i=0; i>2)\ nengel@2: + ((b&0xFCFCFCFCUL)>>2);\ nengel@2: l1= (c&0x03030303UL)\ nengel@2: + (d&0x03030303UL);\ nengel@2: h1= ((c&0xFCFCFCFCUL)>>2)\ nengel@2: + ((d&0xFCFCFCFCUL)>>2);\ nengel@2: OP(*((uint32_t*)&dst[i*dst_stride]), h0+h1+(((l0+l1)>>2)&0x0F0F0F0FUL));\ nengel@2: a= AV_RN32(&src1[i*src_stride1+4]);\ nengel@2: b= AV_RN32(&src2[i*src_stride2+4]);\ nengel@2: c= AV_RN32(&src3[i*src_stride3+4]);\ nengel@2: d= AV_RN32(&src4[i*src_stride4+4]);\ nengel@2: l0= (a&0x03030303UL)\ nengel@2: + (b&0x03030303UL)\ nengel@2: + 0x02020202UL;\ nengel@2: h0= ((a&0xFCFCFCFCUL)>>2)\ nengel@2: + ((b&0xFCFCFCFCUL)>>2);\ nengel@2: l1= (c&0x03030303UL)\ nengel@2: + (d&0x03030303UL);\ nengel@2: h1= ((c&0xFCFCFCFCUL)>>2)\ nengel@2: + ((d&0xFCFCFCFCUL)>>2);\ nengel@2: OP(*((uint32_t*)&dst[i*dst_stride+4]), h0+h1+(((l0+l1)>>2)&0x0F0F0F0FUL));\ nengel@2: }\ nengel@2: }\ nengel@2: \ nengel@2: static inline void OPNAME ## _pixels4_x2_c(uint8_t *block, const uint8_t *pixels, int line_size, int h){\ nengel@2: OPNAME ## _pixels4_l2(block, pixels, pixels+1, line_size, line_size, line_size, h);\ nengel@2: }\ nengel@2: \ nengel@2: static inline void OPNAME ## _pixels4_y2_c(uint8_t *block, const uint8_t *pixels, int line_size, int h){\ nengel@2: OPNAME ## _pixels4_l2(block, pixels, pixels+line_size, line_size, line_size, line_size, h);\ nengel@2: }\ nengel@2: \ nengel@2: static inline void OPNAME ## _pixels2_x2_c(uint8_t *block, const uint8_t *pixels, int line_size, int h){\ nengel@2: OPNAME ## _pixels2_l2(block, pixels, pixels+1, line_size, line_size, line_size, h);\ nengel@2: }\ nengel@2: \ nengel@2: static inline void OPNAME ## _pixels2_y2_c(uint8_t *block, const uint8_t *pixels, int line_size, int h){\ nengel@2: OPNAME ## _pixels2_l2(block, pixels, pixels+line_size, line_size, line_size, line_size, h);\ nengel@2: }\ nengel@2: \ nengel@2: static inline void OPNAME ## _no_rnd_pixels8_l4(uint8_t *dst, const uint8_t *src1, uint8_t *src2, uint8_t *src3, uint8_t *src4,\ nengel@2: int dst_stride, int src_stride1, int src_stride2,int src_stride3,int src_stride4, int h){\ nengel@2: int i;\ nengel@2: for(i=0; i>2)\ nengel@2: + ((b&0xFCFCFCFCUL)>>2);\ nengel@2: l1= (c&0x03030303UL)\ nengel@2: + (d&0x03030303UL);\ nengel@2: h1= ((c&0xFCFCFCFCUL)>>2)\ nengel@2: + ((d&0xFCFCFCFCUL)>>2);\ nengel@2: OP(*((uint32_t*)&dst[i*dst_stride]), h0+h1+(((l0+l1)>>2)&0x0F0F0F0FUL));\ nengel@2: a= AV_RN32(&src1[i*src_stride1+4]);\ nengel@2: b= AV_RN32(&src2[i*src_stride2+4]);\ nengel@2: c= AV_RN32(&src3[i*src_stride3+4]);\ nengel@2: d= AV_RN32(&src4[i*src_stride4+4]);\ nengel@2: l0= (a&0x03030303UL)\ nengel@2: + (b&0x03030303UL)\ nengel@2: + 0x01010101UL;\ nengel@2: h0= ((a&0xFCFCFCFCUL)>>2)\ nengel@2: + ((b&0xFCFCFCFCUL)>>2);\ nengel@2: l1= (c&0x03030303UL)\ nengel@2: + (d&0x03030303UL);\ nengel@2: h1= ((c&0xFCFCFCFCUL)>>2)\ nengel@2: + ((d&0xFCFCFCFCUL)>>2);\ nengel@2: OP(*((uint32_t*)&dst[i*dst_stride+4]), h0+h1+(((l0+l1)>>2)&0x0F0F0F0FUL));\ nengel@2: }\ nengel@2: }\ nengel@2: static inline void OPNAME ## _pixels16_l4(uint8_t *dst, const uint8_t *src1, uint8_t *src2, uint8_t *src3, uint8_t *src4,\ nengel@2: int dst_stride, int src_stride1, int src_stride2,int src_stride3,int src_stride4, int h){\ nengel@2: OPNAME ## _pixels8_l4(dst , src1 , src2 , src3 , src4 , dst_stride, src_stride1, src_stride2, src_stride3, src_stride4, h);\ nengel@2: OPNAME ## _pixels8_l4(dst+8, src1+8, src2+8, src3+8, src4+8, dst_stride, src_stride1, src_stride2, src_stride3, src_stride4, h);\ nengel@2: }\ nengel@2: static inline void OPNAME ## _no_rnd_pixels16_l4(uint8_t *dst, const uint8_t *src1, uint8_t *src2, uint8_t *src3, uint8_t *src4,\ nengel@2: int dst_stride, int src_stride1, int src_stride2,int src_stride3,int src_stride4, int h){\ nengel@2: OPNAME ## _no_rnd_pixels8_l4(dst , src1 , src2 , src3 , src4 , dst_stride, src_stride1, src_stride2, src_stride3, src_stride4, h);\ nengel@2: OPNAME ## _no_rnd_pixels8_l4(dst+8, src1+8, src2+8, src3+8, src4+8, dst_stride, src_stride1, src_stride2, src_stride3, src_stride4, h);\ nengel@2: }\ nengel@2: \ nengel@2: static inline void OPNAME ## _pixels2_xy2_c(uint8_t *block, const uint8_t *pixels, int line_size, int h)\ nengel@2: {\ nengel@2: int i, a0, b0, a1, b1;\ nengel@2: a0= pixels[0];\ nengel@2: b0= pixels[1] + 2;\ nengel@2: a0 += b0;\ nengel@2: b0 += pixels[2];\ nengel@2: \ nengel@2: pixels+=line_size;\ nengel@2: for(i=0; i>2; /* FIXME non put */\ nengel@2: block[1]= (b1+b0)>>2;\ nengel@2: \ nengel@2: pixels+=line_size;\ nengel@2: block +=line_size;\ nengel@2: \ nengel@2: a0= pixels[0];\ nengel@2: b0= pixels[1] + 2;\ nengel@2: a0 += b0;\ nengel@2: b0 += pixels[2];\ nengel@2: \ nengel@2: block[0]= (a1+a0)>>2;\ nengel@2: block[1]= (b1+b0)>>2;\ nengel@2: pixels+=line_size;\ nengel@2: block +=line_size;\ nengel@2: }\ nengel@2: }\ nengel@2: \ nengel@2: static inline void OPNAME ## _pixels4_xy2_c(uint8_t *block, const uint8_t *pixels, int line_size, int h)\ nengel@2: {\ nengel@2: int i;\ nengel@2: const uint32_t a= AV_RN32(pixels );\ nengel@2: const uint32_t b= AV_RN32(pixels+1);\ nengel@2: uint32_t l0= (a&0x03030303UL)\ nengel@2: + (b&0x03030303UL)\ nengel@2: + 0x02020202UL;\ nengel@2: uint32_t h0= ((a&0xFCFCFCFCUL)>>2)\ nengel@2: + ((b&0xFCFCFCFCUL)>>2);\ nengel@2: uint32_t l1,h1;\ nengel@2: \ nengel@2: pixels+=line_size;\ nengel@2: for(i=0; i>2)\ nengel@2: + ((b&0xFCFCFCFCUL)>>2);\ nengel@2: OP(*((uint32_t*)block), h0+h1+(((l0+l1)>>2)&0x0F0F0F0FUL));\ nengel@2: pixels+=line_size;\ nengel@2: block +=line_size;\ nengel@2: a= AV_RN32(pixels );\ nengel@2: b= AV_RN32(pixels+1);\ nengel@2: l0= (a&0x03030303UL)\ nengel@2: + (b&0x03030303UL)\ nengel@2: + 0x02020202UL;\ nengel@2: h0= ((a&0xFCFCFCFCUL)>>2)\ nengel@2: + ((b&0xFCFCFCFCUL)>>2);\ nengel@2: OP(*((uint32_t*)block), h0+h1+(((l0+l1)>>2)&0x0F0F0F0FUL));\ nengel@2: pixels+=line_size;\ nengel@2: block +=line_size;\ nengel@2: }\ nengel@2: }\ nengel@2: \ nengel@2: static inline void OPNAME ## _pixels8_xy2_c(uint8_t *block, const uint8_t *pixels, int line_size, int h)\ nengel@2: {\ nengel@2: int j;\ nengel@2: for(j=0; j<2; j++){\ nengel@2: int i;\ nengel@2: const uint32_t a= AV_RN32(pixels );\ nengel@2: const uint32_t b= AV_RN32(pixels+1);\ nengel@2: uint32_t l0= (a&0x03030303UL)\ nengel@2: + (b&0x03030303UL)\ nengel@2: + 0x02020202UL;\ nengel@2: uint32_t h0= ((a&0xFCFCFCFCUL)>>2)\ nengel@2: + ((b&0xFCFCFCFCUL)>>2);\ nengel@2: uint32_t l1,h1;\ nengel@2: \ nengel@2: pixels+=line_size;\ nengel@2: for(i=0; i>2)\ nengel@2: + ((b&0xFCFCFCFCUL)>>2);\ nengel@2: OP(*((uint32_t*)block), h0+h1+(((l0+l1)>>2)&0x0F0F0F0FUL));\ nengel@2: pixels+=line_size;\ nengel@2: block +=line_size;\ nengel@2: a= AV_RN32(pixels );\ nengel@2: b= AV_RN32(pixels+1);\ nengel@2: l0= (a&0x03030303UL)\ nengel@2: + (b&0x03030303UL)\ nengel@2: + 0x02020202UL;\ nengel@2: h0= ((a&0xFCFCFCFCUL)>>2)\ nengel@2: + ((b&0xFCFCFCFCUL)>>2);\ nengel@2: OP(*((uint32_t*)block), h0+h1+(((l0+l1)>>2)&0x0F0F0F0FUL));\ nengel@2: pixels+=line_size;\ nengel@2: block +=line_size;\ nengel@2: }\ nengel@2: pixels+=4-line_size*(h+1);\ nengel@2: block +=4-line_size*h;\ nengel@2: }\ nengel@2: }\ nengel@2: \ nengel@2: static inline void OPNAME ## _no_rnd_pixels8_xy2_c(uint8_t *block, const uint8_t *pixels, int line_size, int h)\ nengel@2: {\ nengel@2: int j;\ nengel@2: for(j=0; j<2; j++){\ nengel@2: int i;\ nengel@2: const uint32_t a= AV_RN32(pixels );\ nengel@2: const uint32_t b= AV_RN32(pixels+1);\ nengel@2: uint32_t l0= (a&0x03030303UL)\ nengel@2: + (b&0x03030303UL)\ nengel@2: + 0x01010101UL;\ nengel@2: uint32_t h0= ((a&0xFCFCFCFCUL)>>2)\ nengel@2: + ((b&0xFCFCFCFCUL)>>2);\ nengel@2: uint32_t l1,h1;\ nengel@2: \ nengel@2: pixels+=line_size;\ nengel@2: for(i=0; i>2)\ nengel@2: + ((b&0xFCFCFCFCUL)>>2);\ nengel@2: OP(*((uint32_t*)block), h0+h1+(((l0+l1)>>2)&0x0F0F0F0FUL));\ nengel@2: pixels+=line_size;\ nengel@2: block +=line_size;\ nengel@2: a= AV_RN32(pixels );\ nengel@2: b= AV_RN32(pixels+1);\ nengel@2: l0= (a&0x03030303UL)\ nengel@2: + (b&0x03030303UL)\ nengel@2: + 0x01010101UL;\ nengel@2: h0= ((a&0xFCFCFCFCUL)>>2)\ nengel@2: + ((b&0xFCFCFCFCUL)>>2);\ nengel@2: OP(*((uint32_t*)block), h0+h1+(((l0+l1)>>2)&0x0F0F0F0FUL));\ nengel@2: pixels+=line_size;\ nengel@2: block +=line_size;\ nengel@2: }\ nengel@2: pixels+=4-line_size*(h+1);\ nengel@2: block +=4-line_size*h;\ nengel@2: }\ nengel@2: }\ nengel@2: \ nengel@2: CALL_2X_PIXELS(OPNAME ## _pixels16_c , OPNAME ## _pixels8_c , 8)\ nengel@2: nengel@2: #define op_avg(a, b) a = rnd_avg32(a, b) nengel@2: nengel@2: #define op_put(a, b) a = b nengel@2: nengel@2: PIXOP2(avg, op_avg) nengel@2: PIXOP2(put, op_put) nengel@2: #undef op_avg nengel@2: #undef op_put nengel@2: nengel@2: nengel@2: #define H264_CHROMA_MC(OPNAME, OP)\ nengel@2: static void OPNAME ## h264_chroma_mc2_c(uint8_t *dst/*align 8*/, uint8_t *src/*align 1*/, int stride, int h, int x, int y){\ nengel@2: const int A=(8-x)*(8-y);\ nengel@2: const int B=( x)*(8-y);\ nengel@2: const int C=(8-x)*( y);\ nengel@2: const int D=( x)*( y);\ nengel@2: int i;\ nengel@2: \ nengel@2: assert(x<8 && y<8 && x>=0 && y>=0);\ nengel@2: \ nengel@2: if(D){\ nengel@2: for(i=0; i=0 && y>=0);\ nengel@2: \ nengel@2: if(D){\ nengel@2: for(i=0; i=0 && y>=0);\ nengel@2: \ nengel@2: if(D){\ nengel@2: for(i=0; i>6)+1)>>1) nengel@2: #define op_put(a, b) a = (((b) + 32)>>6) nengel@2: nengel@2: H264_CHROMA_MC(put_ , op_put) nengel@2: H264_CHROMA_MC(avg_ , op_avg) nengel@2: #undef op_avg nengel@2: #undef op_put nengel@2: nengel@2: nengel@2: #define H264_LOWPASS(OPNAME, OP, OP2) \ nengel@2: static av_unused void OPNAME ## h264_qpel2_h_lowpass(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\ nengel@2: const int h=2;\ nengel@2: uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;\ nengel@2: int i;\ nengel@2: for(i=0; i>5]+1)>>1) nengel@2: #define op_put(a, b) a = cm[((b) + 16)>>5] nengel@2: #define op2_avg(a, b) a = (((a)+cm[((b) + 512)>>10]+1)>>1) nengel@2: #define op2_put(a, b) a = cm[((b) + 512)>>10] nengel@2: nengel@2: H264_LOWPASS(put_ , op_put, op2_put) nengel@2: H264_LOWPASS(avg_ , op_avg, op2_avg) nengel@2: H264_MC(put_, 2) nengel@2: H264_MC(put_, 4) nengel@2: H264_MC(put_, 8) nengel@2: H264_MC(put_, 16) nengel@2: H264_MC(avg_, 4) nengel@2: H264_MC(avg_, 8) nengel@2: H264_MC(avg_, 16) nengel@2: nengel@2: #undef op_avg nengel@2: #undef op_put nengel@2: #undef op2_avg nengel@2: #undef op2_put nengel@2: nengel@2: static void clear_block_c(DCTELEM *block) nengel@2: { nengel@2: memset(block, 0, sizeof(DCTELEM)*64); nengel@2: } nengel@2: nengel@2: /** nengel@2: * memset(blocks, 0, sizeof(DCTELEM)*6*64) nengel@2: */ nengel@2: static void clear_blocks_c(DCTELEM *blocks) nengel@2: { nengel@2: memset(blocks, 0, sizeof(DCTELEM)*6*64); nengel@2: } nengel@2: nengel@2: static void just_return(void *mem av_unused, int stride av_unused, int h av_unused) { return; } nengel@2: nengel@2: /* init static data */ nengel@2: av_cold void dsputil_static_init(void) nengel@2: { nengel@2: int i; nengel@2: nengel@2: for(i=0;i<256;i++) ff_cropTbl[i + MAX_NEG_CROP] = i; nengel@2: for(i=0;i= 4.2.\n" nengel@2: "Do not report crashes to FFmpeg developers.\n"); nengel@2: #endif nengel@2: did_fail=1; nengel@2: } nengel@2: return -1; nengel@2: } nengel@2: return 0; nengel@2: } nengel@2: nengel@2: av_cold void dsputil_init(DSPContext* c) nengel@2: { nengel@2: (void) avg_pixels2_c; // kill a warning, avg_pixels2_c is a macro created function. nengel@2: ff_check_alignment(); nengel@2: dsputil_static_init(); nengel@2: nengel@2: c->idct_put= ff_simple_idct_put; nengel@2: c->idct_add= ff_simple_idct_add; nengel@2: c->idct = ff_simple_idct; nengel@2: nengel@2: c->clear_block = clear_block_c; nengel@2: c->clear_blocks = clear_blocks_c; nengel@2: nengel@2: #define dspfunc(PFX, IDX, NUM) \ nengel@2: c->PFX ## _pixels_tab[IDX][ 0] = PFX ## NUM ## _mc00_c; \ nengel@2: c->PFX ## _pixels_tab[IDX][ 1] = PFX ## NUM ## _mc10_c; \ nengel@2: c->PFX ## _pixels_tab[IDX][ 2] = PFX ## NUM ## _mc20_c; \ nengel@2: c->PFX ## _pixels_tab[IDX][ 3] = PFX ## NUM ## _mc30_c; \ nengel@2: c->PFX ## _pixels_tab[IDX][ 4] = PFX ## NUM ## _mc01_c; \ nengel@2: c->PFX ## _pixels_tab[IDX][ 5] = PFX ## NUM ## _mc11_c; \ nengel@2: c->PFX ## _pixels_tab[IDX][ 6] = PFX ## NUM ## _mc21_c; \ nengel@2: c->PFX ## _pixels_tab[IDX][ 7] = PFX ## NUM ## _mc31_c; \ nengel@2: c->PFX ## _pixels_tab[IDX][ 8] = PFX ## NUM ## _mc02_c; \ nengel@2: c->PFX ## _pixels_tab[IDX][ 9] = PFX ## NUM ## _mc12_c; \ nengel@2: c->PFX ## _pixels_tab[IDX][10] = PFX ## NUM ## _mc22_c; \ nengel@2: c->PFX ## _pixels_tab[IDX][11] = PFX ## NUM ## _mc32_c; \ nengel@2: c->PFX ## _pixels_tab[IDX][12] = PFX ## NUM ## _mc03_c; \ nengel@2: c->PFX ## _pixels_tab[IDX][13] = PFX ## NUM ## _mc13_c; \ nengel@2: c->PFX ## _pixels_tab[IDX][14] = PFX ## NUM ## _mc23_c; \ nengel@2: c->PFX ## _pixels_tab[IDX][15] = PFX ## NUM ## _mc33_c nengel@2: nengel@2: nengel@2: dspfunc(put_h264_qpel, 0, 16); nengel@2: dspfunc(put_h264_qpel, 1, 8); nengel@2: dspfunc(put_h264_qpel, 2, 4); nengel@2: dspfunc(put_h264_qpel, 3, 2); nengel@2: dspfunc(avg_h264_qpel, 0, 16); nengel@2: dspfunc(avg_h264_qpel, 1, 8); nengel@2: dspfunc(avg_h264_qpel, 2, 4); nengel@2: nengel@2: #undef dspfunc nengel@2: c->put_h264_chroma_pixels_tab[0]= put_h264_chroma_mc8_c; nengel@2: c->put_h264_chroma_pixels_tab[1]= put_h264_chroma_mc4_c; nengel@2: c->put_h264_chroma_pixels_tab[2]= put_h264_chroma_mc2_c; nengel@2: c->avg_h264_chroma_pixels_tab[0]= avg_h264_chroma_mc8_c; nengel@2: c->avg_h264_chroma_pixels_tab[1]= avg_h264_chroma_mc4_c; nengel@2: c->avg_h264_chroma_pixels_tab[2]= avg_h264_chroma_mc2_c; nengel@2: nengel@2: nengel@2: c->prefetch= just_return; nengel@2: nengel@2: if (HAVE_MMX) dsputil_init_mmx (c); nengel@2: if (ARCH_ARM) dsputil_init_arm (c); nengel@2: if (HAVE_ALTIVEC) dsputil_init_ppc (c); //fixme PPC prefetch nengel@2: } nengel@2: