# HG changeset patch # User lorenm # Date 1144142625 0 # Node ID 7aa9f80e79542a75123e9ef976246765effbd4fc # Parent ac7bfc9bf1a4f3680eaf196e6666294b6ac1d09b mmx implementation of 3-point GMC. (5x faster than C) diff -r ac7bfc9bf1a4 -r 7aa9f80e7954 dsputil.c --- a/dsputil.c Mon Apr 03 07:52:24 2006 +0000 +++ b/dsputil.c Tue Apr 04 09:23:45 2006 +0000 @@ -1144,7 +1144,7 @@ } } -static void gmc_c(uint8_t *dst, uint8_t *src, int stride, int h, int ox, int oy, +void ff_gmc_c(uint8_t *dst, uint8_t *src, int stride, int h, int ox, int oy, int dxx, int dxy, int dyx, int dyy, int shift, int r, int width, int height) { int y, vx, vy; @@ -3865,7 +3865,7 @@ c->add_pixels8 = add_pixels8_c; c->add_pixels4 = add_pixels4_c; c->gmc1 = gmc1_c; - c->gmc = gmc_c; + c->gmc = ff_gmc_c; c->clear_blocks = clear_blocks_c; c->pix_sum = pix_sum_c; c->pix_norm1 = pix_norm1_c; diff -r ac7bfc9bf1a4 -r 7aa9f80e7954 dsputil.h --- a/dsputil.h Mon Apr 03 07:52:24 2006 +0000 +++ b/dsputil.h Tue Apr 04 09:23:45 2006 +0000 @@ -82,6 +82,9 @@ void ff_shrink44(uint8_t *dst, int dst_wrap, const uint8_t *src, int src_wrap, int width, int height); void ff_shrink88(uint8_t *dst, int dst_wrap, const uint8_t *src, int src_wrap, int width, int height); +void ff_gmc_c(uint8_t *dst, uint8_t *src, int stride, int h, int ox, int oy, + int dxx, int dxy, int dyx, int dyy, int shift, int r, int width, int height); + /* minimum alignment rules ;) if u notice errors in the align stuff, need more alignment for some asm code for some cpu or need to use a function with less aligned data then send a mail to the ffmpeg-dev list, ... diff -r ac7bfc9bf1a4 -r 7aa9f80e7954 i386/dsputil_mmx.c --- a/i386/dsputil_mmx.c Mon Apr 03 07:52:24 2006 +0000 +++ b/i386/dsputil_mmx.c Tue Apr 04 09:23:45 2006 +0000 @@ -2403,6 +2403,126 @@ c->put_no_rnd_ ## postfix1 = put_no_rnd_ ## postfix2;\ c->avg_ ## postfix1 = avg_ ## postfix2; +static void gmc_mmx(uint8_t *dst, uint8_t *src, int stride, int h, int ox, int oy, + int dxx, int dxy, int dyx, int dyy, int shift, int r, int width, int height){ + const int w = 8; + const int s = 1<>(16+shift); + const int iy = oy>>(16+shift); + const int oxs = ox>>4; + const int oys = oy>>4; + const int dxxs = dxx>>4; + const int dxys = dxy>>4; + const int dyxs = dyx>>4; + const int dyys = dyy>>4; + const uint16_t r4[4] = {r,r,r,r}; + const uint16_t dxy4[4] = {dxys,dxys,dxys,dxys}; + const uint16_t dyy4[4] = {dyys,dyys,dyys,dyys}; + const uint64_t shift2 = 2*shift; + uint8_t edge_buf[(h+1)*stride]; + int x, y; + + const int dxw = (dxx-(1<<(16+shift)))*(w-1); + const int dyh = (dyy-(1<<(16+shift)))*(h-1); + const int dxh = dxy*(h-1); + const int dyw = dyx*(w-1); + if( // non-constant fullpel offset (3% of blocks) + (ox^(ox+dxw) | ox^(ox+dxh) | ox^(ox+dxw+dxh) | + oy^(oy+dyw) | oy^(oy+dyh) | oy^(oy+dyw+dyh)) >> (16+shift) + // uses more than 16 bits of subpel mv (only at huge resolution) + || (dxx|dxy|dyx|dyy)&15 ) + { + //FIXME could still use mmx for some of the rows + ff_gmc_c(dst, src, stride, h, ox, oy, dxx, dxy, dyx, dyy, shift, r, width, height); + return; + } + + if( (unsigned)ix >= width-w || + (unsigned)iy >= height-h ) + { + ff_emulated_edge_mc(edge_buf, src+ix+iy*stride, stride, w+1, h+1, ix, iy, width, height); + src = edge_buf; + } + else + src += ix + iy*stride; + + for(x=0; xavg_no_rnd_pixels_tab[1][2] = avg_no_rnd_pixels8_y2_mmx; c->avg_no_rnd_pixels_tab[1][3] = avg_no_rnd_pixels8_xy2_mmx; + c->gmc= gmc_mmx; + c->add_bytes= add_bytes_mmx; #ifdef CONFIG_ENCODERS c->diff_bytes= diff_bytes_mmx;