Merge commit '6906b19346ae8a330bfaa1c16ce535be10789723'
authorMichael Niedermayer <michaelni@gmx.at>
Fri, 21 Dec 2012 16:18:43 +0000 (17:18 +0100)
committerMichael Niedermayer <michaelni@gmx.at>
Fri, 21 Dec 2012 16:18:43 +0000 (17:18 +0100)
* commit '6906b19346ae8a330bfaa1c16ce535be10789723':
  lavc: add missing files for arm
  lavc: introduce VideoDSPContext

Conflicts:
configure
libavcodec/arm/dsputil_init_armv5te.c
libavcodec/dsputil.c
libavcodec/dsputil.h
libavcodec/dsputil_template.c
libavcodec/h264.c
libavcodec/mpegvideo.h
libavcodec/mpegvideo_enc.c
libavcodec/x86/dsputil_mmx.c

Merged-by: Michael Niedermayer <michaelni@gmx.at>
33 files changed:
1  2 
configure
libavcodec/Makefile
libavcodec/arm/dsputil_arm.S
libavcodec/arm/dsputil_init_armv5te.c
libavcodec/arm/videodsp_init_armv5te.c
libavcodec/cavs.c
libavcodec/dsputil.c
libavcodec/dsputil.h
libavcodec/dsputil_template.c
libavcodec/h264.c
libavcodec/h264_mb_template.c
libavcodec/mpegvideo.c
libavcodec/mpegvideo.h
libavcodec/mpegvideo_enc.c
libavcodec/mpegvideo_motion.c
libavcodec/ppc/dsputil_ppc.c
libavcodec/rv34.c
libavcodec/snow.c
libavcodec/snow.h
libavcodec/svq3.c
libavcodec/vc1dec.c
libavcodec/videodsp.c
libavcodec/videodsp_template.c
libavcodec/vp3.c
libavcodec/vp56.c
libavcodec/vp56.h
libavcodec/vp8.c
libavcodec/vp8.h
libavcodec/wmv2.c
libavcodec/x86/Makefile
libavcodec/x86/dsputil.asm
libavcodec/x86/dsputil_mmx.c
libavcodec/x86/videodsp_init.c

diff --cc configure
+++ b/configure
@@@ -1726,7 -1545,7 +1727,8 @@@ mpeg4_decoder_select="h263_decoder mpeg
  mpeg4_encoder_select="h263_encoder"
  mpeg4_vaapi_hwaccel_select="vaapi mpeg4_decoder"
  mpeg4_vdpau_decoder_select="vdpau mpeg4_decoder"
+ mpegvideo_select="videodsp"
 +msmpeg4_crystalhd_decoder_select="crystalhd"
  msmpeg4v1_decoder_select="h263_decoder"
  msmpeg4v1_encoder_select="h263_encoder"
  msmpeg4v2_decoder_select="h263_decoder"
Simple merge
Simple merge
@@@ -25,11 -25,9 +25,9 @@@ void ff_simple_idct_armv5te(DCTELEM *da
  void ff_simple_idct_put_armv5te(uint8_t *dest, int line_size, DCTELEM *data);
  void ff_simple_idct_add_armv5te(uint8_t *dest, int line_size, DCTELEM *data);
  
- void ff_prefetch_arm(void *mem, int stride, int h);
  av_cold void ff_dsputil_init_armv5te(DSPContext *c, AVCodecContext *avctx)
  {
 -    if (avctx->bits_per_raw_sample <= 8 &&
 +    if (!avctx->lowres && avctx->bits_per_raw_sample <= 8 &&
          (avctx->idct_algo == FF_IDCT_AUTO ||
           avctx->idct_algo == FF_IDCT_SIMPLEARMV5TE)) {
          c->idct_put              = ff_simple_idct_put_armv5te;
index 0000000,a7b8b23..3606012
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,30 +1,32 @@@
+ /*
+  * Copyright (C) 2012 Ronald S. Bultje
+  *
+  * This file is part of Libav.
+  *
+  * Libav 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.
+  *
+  * Libav 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 Libav; if not, write to the Free Software
+  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+  */
+ #include "libavutil/arm/cpu.h"
+ #include <libavcodec/videodsp.h>
+ #include "videodsp_arm.h"
+ void ff_prefetch_arm(uint8_t *mem, ptrdiff_t stride, int h);
+ void ff_videodsp_init_armv5te(VideoDSPContext *ctx, int bpc)
+ {
++#if HAVE_ARMV5TE_EXTERNAL
+     ctx->prefetch = ff_prefetch_arm;
++#endif
+ }
Simple merge
@@@ -2737,39 -2615,6 +2737,37 @@@ static void ff_jref_idct_add(uint8_t *d
      add_pixels_clamped_c(block, dest, line_size);
  }
  
- static void just_return(void *mem av_unused, int stride av_unused, int h av_unused) { return; }
 +static void ff_jref_idct4_put(uint8_t *dest, int line_size, DCTELEM *block)
 +{
 +    ff_j_rev_dct4 (block);
 +    put_pixels_clamped4_c(block, dest, line_size);
 +}
 +static void ff_jref_idct4_add(uint8_t *dest, int line_size, DCTELEM *block)
 +{
 +    ff_j_rev_dct4 (block);
 +    add_pixels_clamped4_c(block, dest, line_size);
 +}
 +
 +static void ff_jref_idct2_put(uint8_t *dest, int line_size, DCTELEM *block)
 +{
 +    ff_j_rev_dct2 (block);
 +    put_pixels_clamped2_c(block, dest, line_size);
 +}
 +static void ff_jref_idct2_add(uint8_t *dest, int line_size, DCTELEM *block)
 +{
 +    ff_j_rev_dct2 (block);
 +    add_pixels_clamped2_c(block, dest, line_size);
 +}
 +
 +static void ff_jref_idct1_put(uint8_t *dest, int line_size, DCTELEM *block)
 +{
 +    dest[0] = av_clip_uint8((block[0] + 4)>>3);
 +}
 +static void ff_jref_idct1_add(uint8_t *dest, int line_size, DCTELEM *block)
 +{
 +    dest[0] = av_clip_uint8(dest[0] + ((block[0] + 4)>>3));
 +}
 +
  /* init static data */
  av_cold void ff_dsputil_static_init(void)
  {
@@@ -195,17 -188,6 +195,14 @@@ void ff_init_scantable(uint8_t *, ScanT
  void ff_init_scantable_permutation(uint8_t *idct_permutation,
                                     int idct_permutation_type);
  
- void ff_emulated_edge_mc_ ## depth (uint8_t *buf, const uint8_t *src, int linesize,\
 +#define EMULATED_EDGE(depth) \
- EMULATED_EDGE(9)
- EMULATED_EDGE(10)
- EMULATED_EDGE(12)
- EMULATED_EDGE(14)
++void ff_emulated_edge_mc_ ## depth (uint8_t *buf, const uint8_t *src, ptrdiff_t linesize,\
 +                         int block_w, int block_h,\
 +                         int src_x, int src_y, int w, int h);
 +
 +EMULATED_EDGE(8)
++EMULATED_EDGE(16)
 +
  /**
   * DSPContext.
   */
@@@ -113,92 -113,8 +113,8 @@@ static void FUNCC(draw_edges)(uint8_t *
              memcpy(last_line + (i + 1) * wrap, last_line, (width + w + w) * sizeof(pixel)); // bottom
  }
  
- /**
-  * Copy a rectangular area of samples to a temporary buffer and replicate the border samples.
-  * @param buf destination buffer
-  * @param src source buffer
-  * @param linesize number of bytes between 2 vertically adjacent samples in both the source and destination buffers
-  * @param block_w width of block
-  * @param block_h height of block
-  * @param src_x x coordinate of the top left sample of the block in the source buffer
-  * @param src_y y coordinate of the top left sample of the block in the source buffer
-  * @param w width of the source buffer
-  * @param h height of the source buffer
-  */
- void FUNC(ff_emulated_edge_mc)(uint8_t *buf, const uint8_t *src, int linesize, int block_w, int block_h,
-                                     int src_x, int src_y, int w, int h){
-     int x, y;
-     int start_y, start_x, end_y, end_x;
-     if(!w || !h)
-         return;
-     if(src_y>= h){
-         src-= src_y*linesize;
-         src+= (h-1)*linesize;
-         src_y=h-1;
-     }else if(src_y<=-block_h){
-         src-= src_y*linesize;
-         src+= (1-block_h)*linesize;
-         src_y=1-block_h;
-     }
-     if(src_x>= w){
-         src+= (w-1-src_x)*sizeof(pixel);
-         src_x=w-1;
-     }else if(src_x<=-block_w){
-         src+= (1-block_w-src_x)*sizeof(pixel);
-         src_x=1-block_w;
-     }
-     start_y= FFMAX(0, -src_y);
-     start_x= FFMAX(0, -src_x);
-     end_y= FFMIN(block_h, h-src_y);
-     end_x= FFMIN(block_w, w-src_x);
-     av_assert2(start_y < end_y && block_h);
-     av_assert2(start_x < end_x && block_w);
-     w    = end_x - start_x;
-     src += start_y*linesize + start_x*sizeof(pixel);
-     buf += start_x*sizeof(pixel);
-     //top
-     for(y=0; y<start_y; y++){
-         memcpy(buf, src, w*sizeof(pixel));
-         buf += linesize;
-     }
-     // copy existing part
-     for(; y<end_y; y++){
-         memcpy(buf, src, w*sizeof(pixel));
-         src += linesize;
-         buf += linesize;
-     }
-     //bottom
-     src -= linesize;
-     for(; y<block_h; y++){
-         memcpy(buf, src, w*sizeof(pixel));
-         buf += linesize;
-     }
-     buf -= block_h * linesize + start_x*sizeof(pixel);
-     while (block_h--){
-         pixel *bufp = (pixel*)buf;
-        //left
-         for(x=0; x<start_x; x++){
-             bufp[x] = bufp[start_x];
-         }
-        //right
-         for(x=end_x; x<block_w; x++){
-             bufp[x] = bufp[end_x - 1];
-         }
-         buf += linesize;
-     }
- }
  #define DCTELEM_FUNCS(dctcoef, suffix)                                  \
 -static void FUNCC(get_pixels ## suffix)(DCTELEM *restrict _block,       \
 +static void FUNCC(get_pixels ## suffix)(DCTELEM *av_restrict _block,    \
                                          const uint8_t *_pixels,         \
                                          int line_size)                  \
  {                                                                       \
@@@ -754,13 -735,15 +754,13 @@@ static av_always_inline void prefetch_m
          int off       = (mx << pixel_shift) +
                          (my + (s->mb_x & 3) * 4) * h->mb_linesize +
                          (64 << pixel_shift);
-         s->dsp.prefetch(src[0] + off, s->linesize, 4);
+         s->vdsp.prefetch(src[0] + off, s->linesize, 4);
          if (chroma_idc == 3 /* yuv444 */) {
-             s->dsp.prefetch(src[1] + off, s->linesize, 4);
-             s->dsp.prefetch(src[2] + off, s->linesize, 4);
+             s->vdsp.prefetch(src[1] + off, s->linesize, 4);
+             s->vdsp.prefetch(src[2] + off, s->linesize, 4);
          } else {
 -            off = ((mx >> 1) << pixel_shift) +
 -                  ((my >> 1) + (s->mb_x & 7)) * s->uvlinesize +
 -                  (64 << pixel_shift);
 +            off= (((mx>>1)+64)<<pixel_shift) + ((my>>1) + (s->mb_x&7))*s->uvlinesize;
-             s->dsp.prefetch(src[1] + off, src[2] - src[1], 2);
+             s->vdsp.prefetch(src[1] + off, src[2] - src[1], 2);
          }
      }
  }
@@@ -993,9 -971,9 +993,10 @@@ static av_cold void common_init(H264Con
      h->dequant_coeff_pps = -1;
      s->unrestricted_mv   = 1;
  
 +    s->dsp.dct_bits = 16;
      /* needed so that IDCT permutation is known early */
      ff_dsputil_init(&s->dsp, s->avctx);
+     ff_videodsp_init(&s->vdsp, 8);
  
      memset(h->pps.scaling_matrix4, 16, 6 * 16 * sizeof(uint8_t));
      memset(h->pps.scaling_matrix8, 16, 2 * 64 * sizeof(uint8_t));
Simple merge
@@@ -172,6 -175,7 +172,7 @@@ const uint8_t *avpriv_mpv_find_start_co
  av_cold int ff_dct_common_init(MpegEncContext *s)
  {
      ff_dsputil_init(&s->dsp, s->avctx);
 -    ff_videodsp_init(&s->vdsp, 8);
++    ff_videodsp_init(&s->vdsp, s->avctx->bits_per_raw_sample > 8 ? 16 : 8);
  
      s->dct_unquantize_h263_intra = dct_unquantize_h263_intra_c;
      s->dct_unquantize_h263_inter = dct_unquantize_h263_inter_c;
@@@ -2005,381 -2026,6 +2006,381 @@@ void ff_print_debug_info(MpegEncContex
      }
  }
  
-         s->dsp.emulated_edge_mc(s->edge_emu_buffer, src, s->linesize, w + 1,
 +static inline int hpel_motion_lowres(MpegEncContext *s,
 +                                     uint8_t *dest, uint8_t *src,
 +                                     int field_based, int field_select,
 +                                     int src_x, int src_y,
 +                                     int width, int height, int stride,
 +                                     int h_edge_pos, int v_edge_pos,
 +                                     int w, int h, h264_chroma_mc_func *pix_op,
 +                                     int motion_x, int motion_y)
 +{
 +    const int lowres   = s->avctx->lowres;
 +    const int op_index = FFMIN(lowres, 2);
 +    const int s_mask   = (2 << lowres) - 1;
 +    int emu = 0;
 +    int sx, sy;
 +
 +    if (s->quarter_sample) {
 +        motion_x /= 2;
 +        motion_y /= 2;
 +    }
 +
 +    sx = motion_x & s_mask;
 +    sy = motion_y & s_mask;
 +    src_x += motion_x >> lowres + 1;
 +    src_y += motion_y >> lowres + 1;
 +
 +    src   += src_y * stride + src_x;
 +
 +    if ((unsigned)src_x > FFMAX( h_edge_pos - (!!sx) - w,                 0) ||
 +        (unsigned)src_y > FFMAX((v_edge_pos >> field_based) - (!!sy) - h, 0)) {
-         s->dsp.emulated_edge_mc(s->edge_emu_buffer, ptr_y,
++        s->vdsp.emulated_edge_mc(s->edge_emu_buffer, src, s->linesize, w + 1,
 +                                (h + 1) << field_based, src_x,
 +                                src_y   << field_based,
 +                                h_edge_pos,
 +                                v_edge_pos);
 +        src = s->edge_emu_buffer;
 +        emu = 1;
 +    }
 +
 +    sx = (sx << 2) >> lowres;
 +    sy = (sy << 2) >> lowres;
 +    if (field_select)
 +        src += s->linesize;
 +    pix_op[op_index](dest, src, stride, h, sx, sy);
 +    return emu;
 +}
 +
 +/* apply one mpeg motion vector to the three components */
 +static av_always_inline void mpeg_motion_lowres(MpegEncContext *s,
 +                                                uint8_t *dest_y,
 +                                                uint8_t *dest_cb,
 +                                                uint8_t *dest_cr,
 +                                                int field_based,
 +                                                int bottom_field,
 +                                                int field_select,
 +                                                uint8_t **ref_picture,
 +                                                h264_chroma_mc_func *pix_op,
 +                                                int motion_x, int motion_y,
 +                                                int h, int mb_y)
 +{
 +    uint8_t *ptr_y, *ptr_cb, *ptr_cr;
 +    int mx, my, src_x, src_y, uvsrc_x, uvsrc_y, uvlinesize, linesize, sx, sy,
 +        uvsx, uvsy;
 +    const int lowres     = s->avctx->lowres;
 +    const int op_index   = FFMIN(lowres-1+s->chroma_x_shift, 2);
 +    const int block_s    = 8>>lowres;
 +    const int s_mask     = (2 << lowres) - 1;
 +    const int h_edge_pos = s->h_edge_pos >> lowres;
 +    const int v_edge_pos = s->v_edge_pos >> lowres;
 +    linesize   = s->current_picture.f.linesize[0] << field_based;
 +    uvlinesize = s->current_picture.f.linesize[1] << field_based;
 +
 +    // FIXME obviously not perfect but qpel will not work in lowres anyway
 +    if (s->quarter_sample) {
 +        motion_x /= 2;
 +        motion_y /= 2;
 +    }
 +
 +    if(field_based){
 +        motion_y += (bottom_field - field_select)*((1 << lowres)-1);
 +    }
 +
 +    sx = motion_x & s_mask;
 +    sy = motion_y & s_mask;
 +    src_x = s->mb_x * 2 * block_s + (motion_x >> lowres + 1);
 +    src_y = (mb_y * 2 * block_s >> field_based) + (motion_y >> lowres + 1);
 +
 +    if (s->out_format == FMT_H263) {
 +        uvsx    = ((motion_x >> 1) & s_mask) | (sx & 1);
 +        uvsy    = ((motion_y >> 1) & s_mask) | (sy & 1);
 +        uvsrc_x = src_x >> 1;
 +        uvsrc_y = src_y >> 1;
 +    } else if (s->out_format == FMT_H261) {
 +        // even chroma mv's are full pel in H261
 +        mx      = motion_x / 4;
 +        my      = motion_y / 4;
 +        uvsx    = (2 * mx) & s_mask;
 +        uvsy    = (2 * my) & s_mask;
 +        uvsrc_x = s->mb_x * block_s + (mx >> lowres);
 +        uvsrc_y =    mb_y * block_s + (my >> lowres);
 +    } else {
 +        if(s->chroma_y_shift){
 +            mx      = motion_x / 2;
 +            my      = motion_y / 2;
 +            uvsx    = mx & s_mask;
 +            uvsy    = my & s_mask;
 +            uvsrc_x = s->mb_x * block_s                 + (mx >> lowres + 1);
 +            uvsrc_y =   (mb_y * block_s >> field_based) + (my >> lowres + 1);
 +        } else {
 +            if(s->chroma_x_shift){
 +            //Chroma422
 +                mx = motion_x / 2;
 +                uvsx = mx & s_mask;
 +                uvsy = motion_y & s_mask;
 +                uvsrc_y = src_y;
 +                uvsrc_x = s->mb_x*block_s               + (mx >> (lowres+1));
 +            } else {
 +            //Chroma444
 +                uvsx = motion_x & s_mask;
 +                uvsy = motion_y & s_mask;
 +                uvsrc_x = src_x;
 +                uvsrc_y = src_y;
 +            }
 +        }
 +    }
 +
 +    ptr_y  = ref_picture[0] + src_y   * linesize   + src_x;
 +    ptr_cb = ref_picture[1] + uvsrc_y * uvlinesize + uvsrc_x;
 +    ptr_cr = ref_picture[2] + uvsrc_y * uvlinesize + uvsrc_x;
 +
 +    if ((unsigned) src_x > FFMAX( h_edge_pos - (!!sx) - 2 * block_s,       0) ||
 +        (unsigned) src_y > FFMAX((v_edge_pos >> field_based) - (!!sy) - h, 0)) {
-             s->dsp.emulated_edge_mc(uvbuf , ptr_cb, uvlinesize >> field_based, 9,
++        s->vdsp.emulated_edge_mc(s->edge_emu_buffer, ptr_y,
 +                                linesize >> field_based, 17, 17 + field_based,
 +                                src_x, src_y << field_based, h_edge_pos,
 +                                v_edge_pos);
 +        ptr_y = s->edge_emu_buffer;
 +        if (!CONFIG_GRAY || !(s->flags & CODEC_FLAG_GRAY)) {
 +            uint8_t *uvbuf = s->edge_emu_buffer + 18 * s->linesize;
-             s->dsp.emulated_edge_mc(uvbuf + 16, ptr_cr, uvlinesize >> field_based, 9,
++            s->vdsp.emulated_edge_mc(uvbuf , ptr_cb, uvlinesize >> field_based, 9,
 +                                    9 + field_based,
 +                                    uvsrc_x, uvsrc_y << field_based,
 +                                    h_edge_pos >> 1, v_edge_pos >> 1);
-             s->dsp.emulated_edge_mc(s->edge_emu_buffer, ptr, s->uvlinesize,
++            s->vdsp.emulated_edge_mc(uvbuf + 16, ptr_cr, uvlinesize >> field_based, 9,
 +                                    9 + field_based,
 +                                    uvsrc_x, uvsrc_y << field_based,
 +                                    h_edge_pos >> 1, v_edge_pos >> 1);
 +            ptr_cb = uvbuf;
 +            ptr_cr = uvbuf + 16;
 +        }
 +    }
 +
 +    // FIXME use this for field pix too instead of the obnoxious hack which changes picture.f.data
 +    if (bottom_field) {
 +        dest_y  += s->linesize;
 +        dest_cb += s->uvlinesize;
 +        dest_cr += s->uvlinesize;
 +    }
 +
 +    if (field_select) {
 +        ptr_y   += s->linesize;
 +        ptr_cb  += s->uvlinesize;
 +        ptr_cr  += s->uvlinesize;
 +    }
 +
 +    sx = (sx << 2) >> lowres;
 +    sy = (sy << 2) >> lowres;
 +    pix_op[lowres - 1](dest_y, ptr_y, linesize, h, sx, sy);
 +
 +    if (!CONFIG_GRAY || !(s->flags & CODEC_FLAG_GRAY)) {
 +        uvsx = (uvsx << 2) >> lowres;
 +        uvsy = (uvsy << 2) >> lowres;
 +        if (h >> s->chroma_y_shift) {
 +            pix_op[op_index](dest_cb, ptr_cb, uvlinesize, h >> s->chroma_y_shift, uvsx, uvsy);
 +            pix_op[op_index](dest_cr, ptr_cr, uvlinesize, h >> s->chroma_y_shift, uvsx, uvsy);
 +        }
 +    }
 +    // FIXME h261 lowres loop filter
 +}
 +
 +static inline void chroma_4mv_motion_lowres(MpegEncContext *s,
 +                                            uint8_t *dest_cb, uint8_t *dest_cr,
 +                                            uint8_t **ref_picture,
 +                                            h264_chroma_mc_func * pix_op,
 +                                            int mx, int my)
 +{
 +    const int lowres     = s->avctx->lowres;
 +    const int op_index   = FFMIN(lowres, 2);
 +    const int block_s    = 8 >> lowres;
 +    const int s_mask     = (2 << lowres) - 1;
 +    const int h_edge_pos = s->h_edge_pos >> lowres + 1;
 +    const int v_edge_pos = s->v_edge_pos >> lowres + 1;
 +    int emu = 0, src_x, src_y, offset, sx, sy;
 +    uint8_t *ptr;
 +
 +    if (s->quarter_sample) {
 +        mx /= 2;
 +        my /= 2;
 +    }
 +
 +    /* In case of 8X8, we construct a single chroma motion vector
 +       with a special rounding */
 +    mx = ff_h263_round_chroma(mx);
 +    my = ff_h263_round_chroma(my);
 +
 +    sx = mx & s_mask;
 +    sy = my & s_mask;
 +    src_x = s->mb_x * block_s + (mx >> lowres + 1);
 +    src_y = s->mb_y * block_s + (my >> lowres + 1);
 +
 +    offset = src_y * s->uvlinesize + src_x;
 +    ptr = ref_picture[1] + offset;
 +    if (s->flags & CODEC_FLAG_EMU_EDGE) {
 +        if ((unsigned) src_x > FFMAX(h_edge_pos - (!!sx) - block_s, 0) ||
 +            (unsigned) src_y > FFMAX(v_edge_pos - (!!sy) - block_s, 0)) {
-         s->dsp.emulated_edge_mc(s->edge_emu_buffer, ptr, s->uvlinesize, 9, 9,
++            s->vdsp.emulated_edge_mc(s->edge_emu_buffer, ptr, s->uvlinesize,
 +                                    9, 9, src_x, src_y, h_edge_pos, v_edge_pos);
 +            ptr = s->edge_emu_buffer;
 +            emu = 1;
 +        }
 +    }
 +    sx = (sx << 2) >> lowres;
 +    sy = (sy << 2) >> lowres;
 +    pix_op[op_index](dest_cb, ptr, s->uvlinesize, block_s, sx, sy);
 +
 +    ptr = ref_picture[2] + offset;
 +    if (emu) {
++        s->vdsp.emulated_edge_mc(s->edge_emu_buffer, ptr, s->uvlinesize, 9, 9,
 +                                src_x, src_y, h_edge_pos, v_edge_pos);
 +        ptr = s->edge_emu_buffer;
 +    }
 +    pix_op[op_index](dest_cr, ptr, s->uvlinesize, block_s, sx, sy);
 +}
 +
 +/**
 + * motion compensation of a single macroblock
 + * @param s context
 + * @param dest_y luma destination pointer
 + * @param dest_cb chroma cb/u destination pointer
 + * @param dest_cr chroma cr/v destination pointer
 + * @param dir direction (0->forward, 1->backward)
 + * @param ref_picture array[3] of pointers to the 3 planes of the reference picture
 + * @param pix_op halfpel motion compensation function (average or put normally)
 + * the motion vectors are taken from s->mv and the MV type from s->mv_type
 + */
 +static inline void MPV_motion_lowres(MpegEncContext *s,
 +                                     uint8_t *dest_y, uint8_t *dest_cb,
 +                                     uint8_t *dest_cr,
 +                                     int dir, uint8_t **ref_picture,
 +                                     h264_chroma_mc_func *pix_op)
 +{
 +    int mx, my;
 +    int mb_x, mb_y, i;
 +    const int lowres  = s->avctx->lowres;
 +    const int block_s = 8 >>lowres;
 +
 +    mb_x = s->mb_x;
 +    mb_y = s->mb_y;
 +
 +    switch (s->mv_type) {
 +    case MV_TYPE_16X16:
 +        mpeg_motion_lowres(s, dest_y, dest_cb, dest_cr,
 +                           0, 0, 0,
 +                           ref_picture, pix_op,
 +                           s->mv[dir][0][0], s->mv[dir][0][1],
 +                           2 * block_s, mb_y);
 +        break;
 +    case MV_TYPE_8X8:
 +        mx = 0;
 +        my = 0;
 +        for (i = 0; i < 4; i++) {
 +            hpel_motion_lowres(s, dest_y + ((i & 1) + (i >> 1) *
 +                               s->linesize) * block_s,
 +                               ref_picture[0], 0, 0,
 +                               (2 * mb_x + (i & 1)) * block_s,
 +                               (2 * mb_y + (i >> 1)) * block_s,
 +                               s->width, s->height, s->linesize,
 +                               s->h_edge_pos >> lowres, s->v_edge_pos >> lowres,
 +                               block_s, block_s, pix_op,
 +                               s->mv[dir][i][0], s->mv[dir][i][1]);
 +
 +            mx += s->mv[dir][i][0];
 +            my += s->mv[dir][i][1];
 +        }
 +
 +        if (!CONFIG_GRAY || !(s->flags & CODEC_FLAG_GRAY))
 +            chroma_4mv_motion_lowres(s, dest_cb, dest_cr, ref_picture,
 +                                     pix_op, mx, my);
 +        break;
 +    case MV_TYPE_FIELD:
 +        if (s->picture_structure == PICT_FRAME) {
 +            /* top field */
 +            mpeg_motion_lowres(s, dest_y, dest_cb, dest_cr,
 +                               1, 0, s->field_select[dir][0],
 +                               ref_picture, pix_op,
 +                               s->mv[dir][0][0], s->mv[dir][0][1],
 +                               block_s, mb_y);
 +            /* bottom field */
 +            mpeg_motion_lowres(s, dest_y, dest_cb, dest_cr,
 +                               1, 1, s->field_select[dir][1],
 +                               ref_picture, pix_op,
 +                               s->mv[dir][1][0], s->mv[dir][1][1],
 +                               block_s, mb_y);
 +        } else {
 +            if (s->picture_structure != s->field_select[dir][0] + 1 &&
 +                s->pict_type != AV_PICTURE_TYPE_B && !s->first_field) {
 +                ref_picture = s->current_picture_ptr->f.data;
 +
 +            }
 +            mpeg_motion_lowres(s, dest_y, dest_cb, dest_cr,
 +                               0, 0, s->field_select[dir][0],
 +                               ref_picture, pix_op,
 +                               s->mv[dir][0][0],
 +                               s->mv[dir][0][1], 2 * block_s, mb_y >> 1);
 +            }
 +        break;
 +    case MV_TYPE_16X8:
 +        for (i = 0; i < 2; i++) {
 +            uint8_t **ref2picture;
 +
 +            if (s->picture_structure == s->field_select[dir][i] + 1 ||
 +                s->pict_type == AV_PICTURE_TYPE_B || s->first_field) {
 +                ref2picture = ref_picture;
 +            } else {
 +                ref2picture = s->current_picture_ptr->f.data;
 +            }
 +
 +            mpeg_motion_lowres(s, dest_y, dest_cb, dest_cr,
 +                               0, 0, s->field_select[dir][i],
 +                               ref2picture, pix_op,
 +                               s->mv[dir][i][0], s->mv[dir][i][1] +
 +                               2 * block_s * i, block_s, mb_y >> 1);
 +
 +            dest_y  +=  2 * block_s *  s->linesize;
 +            dest_cb += (2 * block_s >> s->chroma_y_shift) * s->uvlinesize;
 +            dest_cr += (2 * block_s >> s->chroma_y_shift) * s->uvlinesize;
 +        }
 +        break;
 +    case MV_TYPE_DMV:
 +        if (s->picture_structure == PICT_FRAME) {
 +            for (i = 0; i < 2; i++) {
 +                int j;
 +                for (j = 0; j < 2; j++) {
 +                    mpeg_motion_lowres(s, dest_y, dest_cb, dest_cr,
 +                                       1, j, j ^ i,
 +                                       ref_picture, pix_op,
 +                                       s->mv[dir][2 * i + j][0],
 +                                       s->mv[dir][2 * i + j][1],
 +                                       block_s, mb_y);
 +                }
 +                pix_op = s->dsp.avg_h264_chroma_pixels_tab;
 +            }
 +        } else {
 +            for (i = 0; i < 2; i++) {
 +                mpeg_motion_lowres(s, dest_y, dest_cb, dest_cr,
 +                                   0, 0, s->picture_structure != i + 1,
 +                                   ref_picture, pix_op,
 +                                   s->mv[dir][2 * i][0],s->mv[dir][2 * i][1],
 +                                   2 * block_s, mb_y >> 1);
 +
 +                // after put we make avg of the same block
 +                pix_op = s->dsp.avg_h264_chroma_pixels_tab;
 +
 +                // opposite parity is always in the same
 +                // frame if this is second field
 +                if (!s->first_field) {
 +                    ref_picture = s->current_picture_ptr->f.data;
 +                }
 +            }
 +        }
 +        break;
 +    default:
 +        av_assert2(0);
 +    }
 +}
 +
  /**
   * find the lowest MB row referenced in the MVs
   */
  #include "parser.h"
  #include "mpeg12data.h"
  #include "rl.h"
- #include "libavutil/timecode.h"
+ #include "videodsp.h"
  
  #include "libavutil/opt.h"
++#include "libavutil/timecode.h"
  
  #define FRAME_SKIPPED 100 ///< return value for header parsers if frame is not coded
  
@@@ -1880,22 -1776,22 +1880,22 @@@ static av_always_inline void encode_mb_
      ptr_y  = s->new_picture.f.data[0] +
               (mb_y * 16 * wrap_y)              + mb_x * 16;
      ptr_cb = s->new_picture.f.data[1] +
 -             (mb_y * mb_block_height * wrap_c) + mb_x * 8;
 +             (mb_y * mb_block_height * wrap_c) + mb_x * mb_block_width;
      ptr_cr = s->new_picture.f.data[2] +
 -             (mb_y * mb_block_height * wrap_c) + mb_x * 8;
 +             (mb_y * mb_block_height * wrap_c) + mb_x * mb_block_width;
  
 -    if (mb_x * 16 + 16 > s->width || mb_y * 16 + 16 > s->height) {
 +    if((mb_x*16+16 > s->width || mb_y*16+16 > s->height) && s->codec_id != AV_CODEC_ID_AMV){
          uint8_t *ebuf = s->edge_emu_buffer + 32;
-         s->dsp.emulated_edge_mc(ebuf, ptr_y, wrap_y, 16, 16, mb_x * 16,
-                                 mb_y * 16, s->width, s->height);
+         s->vdsp.emulated_edge_mc(ebuf, ptr_y, wrap_y, 16, 16, mb_x * 16,
+                                  mb_y * 16, s->width, s->height);
          ptr_y = ebuf;
-         s->dsp.emulated_edge_mc(ebuf + 18 * wrap_y, ptr_cb, wrap_c, mb_block_width,
-                                 mb_block_height, mb_x * 8, mb_y * 8,
-                                 (s->width+1) >> 1, (s->height+1) >> 1);
 -        s->vdsp.emulated_edge_mc(ebuf + 18 * wrap_y, ptr_cb, wrap_c, 8,
++        s->vdsp.emulated_edge_mc(ebuf + 18 * wrap_y, ptr_cb, wrap_c, mb_block_width,
+                                  mb_block_height, mb_x * 8, mb_y * 8,
 -                                 s->width >> 1, s->height >> 1);
++                                 (s->width+1) >> 1, (s->height+1) >> 1);
          ptr_cb = ebuf + 18 * wrap_y;
-         s->dsp.emulated_edge_mc(ebuf + 18 * wrap_y + 8, ptr_cr, wrap_c, mb_block_width,
-                                 mb_block_height, mb_x * 8, mb_y * 8,
-                                 (s->width+1) >> 1, (s->height+1) >> 1);
 -        s->vdsp.emulated_edge_mc(ebuf + 18 * wrap_y + 8, ptr_cr, wrap_c, 8,
++        s->vdsp.emulated_edge_mc(ebuf + 18 * wrap_y + 8, ptr_cr, wrap_c, mb_block_width,
+                                  mb_block_height, mb_x * 8, mb_y * 8,
 -                                 s->width >> 1, s->height >> 1);
++                                 (s->width+1) >> 1, (s->height+1) >> 1);
          ptr_cr = ebuf + 18 * wrap_y + 8;
      }
  
Simple merge
@@@ -140,26 -140,8 +140,16 @@@ static long check_dcbzl_effect(void
  void ff_dsputil_init_ppc(DSPContext* c, AVCodecContext *avctx)
  {
      const int high_bit_depth = avctx->bits_per_raw_sample > 8;
 +    int mm_flags = av_get_cpu_flags();
 +
 +    if (avctx->dsp_mask) {
 +        if (avctx->dsp_mask & AV_CPU_FLAG_FORCE)
 +            mm_flags |= (avctx->dsp_mask & 0xffff);
 +        else
 +            mm_flags &= ~(avctx->dsp_mask & 0xffff);
 +    }
  
      // Common optimizations whether AltiVec is available or not
-     c->prefetch = prefetch_ppc;
      if (!high_bit_depth) {
      switch (check_dcbzl_effect()) {
          case 32:
Simple merge
@@@ -344,18 -347,15 +344,18 @@@ void ff_snow_pred_block(SnowContext *s
          sx += (mx>>4) - (HTAPS_MAX/2-1);
          sy += (my>>4) - (HTAPS_MAX/2-1);
          src += sx + sy*stride;
 -        if(   (unsigned)sx >= w - b_w - (HTAPS_MAX-2)
 -           || (unsigned)sy >= h - b_h - (HTAPS_MAX-2)){
 -            s->dsp.emulated_edge_mc(tmp + MB_SIZE, src, stride, b_w+HTAPS_MAX-1, b_h+HTAPS_MAX-1, sx, sy, w, h);
 +        if(   (unsigned)sx >= FFMAX(w - b_w - (HTAPS_MAX-2), 0)
 +           || (unsigned)sy >= FFMAX(h - b_h - (HTAPS_MAX-2), 0)){
-             s->dsp.emulated_edge_mc(tmp + MB_SIZE, src, stride, b_w+HTAPS_MAX-1, b_h+HTAPS_MAX-1, sx, sy, w, h);
++            s->vdsp.emulated_edge_mc(tmp + MB_SIZE, src, stride, b_w+HTAPS_MAX-1, b_h+HTAPS_MAX-1, sx, sy, w, h);
              src= tmp + MB_SIZE;
          }
 +
 +        av_assert2(s->chroma_h_shift == s->chroma_v_shift); // only one mv_scale
 +
  //        assert(b_w == b_h || 2*b_w == b_h || b_w == 2*b_h);
  //        assert(!(b_w&(b_w-1)));
 -        assert(b_w>1 && b_h>1);
 -        assert((tab_index>=0 && tab_index<4) || b_w==32);
 +        av_assert2(b_w>1 && b_h>1);
 +        av_assert2((tab_index>=0 && tab_index<4) || b_w==32);
          if((dx&3) || (dy&3) || !(b_w == b_h || 2*b_w == b_h || b_w == 2*b_h) || (b_w&(b_w-1)) || !s->plane[plane_index].fast_mc )
              mc_block(&s->plane[plane_index], dst, src, stride, b_w, b_h, dx, dy);
          else if(b_w==32){
@@@ -401,6 -402,6 +401,7 @@@ av_cold int ff_snow_common_init(AVCodec
      s->max_ref_frames=1; //just make sure its not an invalid value in case of no initial keyframe
  
      ff_dsputil_init(&s->dsp, avctx);
++    ff_videodsp_init(&s->vdsp, 8);
      ff_dwt_init(&s->dwt);
  
  #define mcf(dx,dy)\
@@@ -108,6 -108,6 +108,7 @@@ typedef struct SnowContext
      AVCodecContext *avctx;
      RangeCoder c;
      DSPContext dsp;
++    VideoDSPContext vdsp;
      DWTContext dwt;
      AVFrame new_picture;
      AVFrame input_picture;              ///< new_picture with the internal linesizes
Simple merge
Simple merge
index 0000000,d14b0a1..6b32a68
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,51 +1,52 @@@
+ /*
+  * Copyright (C) 2012 Ronald S. Bultje
+  *
+  * This file is part of Libav.
+  *
+  * Libav 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.
+  *
+  * Libav 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 Libav; if not, write to the Free Software
+  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+  */
++#include "libavutil/avassert.h"
+ #include "libavutil/common.h"
+ #include "videodsp.h"
+ #define BIT_DEPTH 8
+ #include "videodsp_template.c"
+ #undef BIT_DEPTH
+ #define BIT_DEPTH 16
+ #include "videodsp_template.c"
+ #undef BIT_DEPTH
+ static void just_return(uint8_t *buf, ptrdiff_t stride, int h)
+ {
+ }
+ void ff_videodsp_init(VideoDSPContext *ctx, int bpc)
+ {
+     ctx->prefetch = just_return;
+     if (bpc <= 8) {
+         ctx->emulated_edge_mc = ff_emulated_edge_mc_8;
+     } else {
+         ctx->emulated_edge_mc = ff_emulated_edge_mc_16;
+     }
+     if (ARCH_ARM)
+         ff_videodsp_init_arm(ctx, bpc);
+     if (ARCH_PPC)
+         ff_videodsp_init_ppc(ctx, bpc);
+     if (ARCH_X86)
+         ff_videodsp_init_x86(ctx, bpc);
+ }
index 0000000,5d5a32f..350a28c
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,93 +1,98 @@@
 -
 -static void FUNC(ff_emulated_edge_mc)(uint8_t *buf, const uint8_t *src,
 -                                      ptrdiff_t linesize,
+ /*
+  * Copyright (c) 2002-2004 Michael Niedermayer
+  * Copyright (C) 2012 Ronald S. Bultje
+  *
+  * This file is part of Libav.
+  *
+  * Libav 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.
+  *
+  * Libav 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 Libav; if not, write to the Free Software
+  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+  */
+ #include "bit_depth_template.c"
 -        src  += (h - 1 - src_y) * linesize;
++void FUNC(ff_emulated_edge_mc)(uint8_t *buf, const uint8_t *src,
++                                      ptrdiff_t linesize_arg,
+                                       int block_w, int block_h,
+                                       int src_x, int src_y, int w, int h)
+ {
+     int x, y;
+     int start_y, start_x, end_y, end_x;
++    int linesize = linesize_arg;
++
++    if (!w || !h)
++        return;
+     if (src_y >= h) {
 -        src  += (1 - block_h - src_y) * linesize;
++        src -= src_y * linesize;
++        src += (h - 1) * linesize;
+         src_y = h - 1;
+     } else if (src_y <= -block_h) {
 -    assert(start_y < end_y && block_h);
 -    assert(start_x < end_x && block_w);
++        src -= src_y * linesize;
++        src += (1 - block_h) * linesize;
+         src_y = 1 - block_h;
+     }
+     if (src_x >= w) {
+         src  += (w - 1 - src_x) * sizeof(pixel);
+         src_x = w - 1;
+     } else if (src_x <= -block_w) {
+         src  += (1 - block_w - src_x) * sizeof(pixel);
+         src_x = 1 - block_w;
+     }
+     start_y = FFMAX(0, -src_y);
+     start_x = FFMAX(0, -src_x);
+     end_y = FFMIN(block_h, h-src_y);
+     end_x = FFMIN(block_w, w-src_x);
++    av_assert2(start_y < end_y && block_h);
++    av_assert2(start_x < end_x && block_w);
+     w    = end_x - start_x;
+     src += start_y * linesize + start_x * sizeof(pixel);
+     buf += start_x * sizeof(pixel);
+     // top
+     for (y = 0; y < start_y; y++) {
+         memcpy(buf, src, w * sizeof(pixel));
+         buf += linesize;
+     }
+     // copy existing part
+     for (; y < end_y; y++) {
+         memcpy(buf, src, w * sizeof(pixel));
+         src += linesize;
+         buf += linesize;
+     }
+     // bottom
+     src -= linesize;
+     for (; y < block_h; y++) {
+         memcpy(buf, src, w * sizeof(pixel));
+         buf += linesize;
+     }
+     buf -= block_h * linesize + start_x * sizeof(pixel);
+     while (block_h--) {
+         pixel *bufp = (pixel *) buf;
+         // left
+         for(x = 0; x < start_x; x++) {
+             bufp[x] = bufp[start_x];
+         }
+         // right
+         for (x = end_x; x < block_w; x++) {
+             bufp[x] = bufp[end_x - 1];
+         }
+         buf += linesize;
+     }
+ }
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -19,9 -17,9 +19,10 @@@ OBJS-$(CONFIG_PRORES_LGPL_DECODER)     
  OBJS-$(CONFIG_RV30_DECODER)            += x86/rv34dsp_init.o
  OBJS-$(CONFIG_RV40_DECODER)            += x86/rv34dsp_init.o            \
                                            x86/rv40dsp_init.o
 +OBJS-$(CONFIG_V210_DECODER)            += x86/v210-init.o
  OBJS-$(CONFIG_TRUEHD_DECODER)          += x86/mlpdsp.o
  OBJS-$(CONFIG_VC1_DECODER)             += x86/vc1dsp_init.o
+ OBJS-$(CONFIG_VIDEODSP)                += x86/videodsp_init.o
  OBJS-$(CONFIG_VP3DSP)                  += x86/vp3dsp_init.o
  OBJS-$(CONFIG_VP5_DECODER)             += x86/vp56dsp_init.o
  OBJS-$(CONFIG_VP6_DECODER)             += x86/vp56dsp_init.o
@@@ -66,8 -60,8 +67,9 @@@ YASM-OBJS-$(CONFIG_PRORES_LGPL_DECODER
  YASM-OBJS-$(CONFIG_RV30_DECODER)       += x86/rv34dsp.o
  YASM-OBJS-$(CONFIG_RV40_DECODER)       += x86/rv34dsp.o                 \
                                            x86/rv40dsp.o
 +YASM-OBJS-$(CONFIG_V210_DECODER)       += x86/v210.o
  YASM-OBJS-$(CONFIG_VC1_DECODER)        += x86/vc1dsp.o
+ YASM-OBJS-$(CONFIG_VIDEODSP)           += x86/videodsp.o
  YASM-OBJS-$(CONFIG_VP3DSP)             += x86/vp3dsp.o
  YASM-OBJS-$(CONFIG_VP6_DECODER)        += x86/vp56dsp.o
  YASM-OBJS-$(CONFIG_VP8_DECODER)        += x86/vp8dsp.o
Simple merge
@@@ -1655,92 -1635,10 +1655,15 @@@ void ff_avg_rv40_qpel16_mc33_mmx(uint8_
    avg_pixels16_xy2_mmx(dst, src, stride, 16);
  }
  
- #endif /* HAVE_INLINE_ASM */
- #if HAVE_YASM
- typedef void emu_edge_core_func(uint8_t *buf, const uint8_t *src,
-                                 x86_reg linesize, x86_reg start_y,
-                                 x86_reg end_y, x86_reg block_h,
-                                 x86_reg start_x, x86_reg end_x,
-                                 x86_reg block_w);
- extern emu_edge_core_func ff_emu_edge_core_mmx;
- extern emu_edge_core_func ff_emu_edge_core_sse;
- static av_always_inline void emulated_edge_mc(uint8_t *buf, const uint8_t *src,
-                                               int linesize,
-                                               int block_w, int block_h,
-                                               int src_x, int src_y,
-                                               int w, int h,
-                                               emu_edge_core_func *core_fn)
- {
-     int start_y, start_x, end_y, end_x, src_y_add = 0;
-     if(!w || !h)
-         return;
-     if (src_y >= h) {
-         src -= src_y*linesize;
-         src_y_add = h - 1;
-         src_y     = h - 1;
-     } else if (src_y <= -block_h) {
-         src -= src_y*linesize;
-         src_y_add = 1 - block_h;
-         src_y     = 1 - block_h;
-     }
-     if (src_x >= w) {
-         src   += w - 1 - src_x;
-         src_x  = w - 1;
-     } else if (src_x <= -block_w) {
-         src   += 1 - block_w - src_x;
-         src_x  = 1 - block_w;
-     }
-     start_y = FFMAX(0, -src_y);
-     start_x = FFMAX(0, -src_x);
-     end_y   = FFMIN(block_h, h-src_y);
-     end_x   = FFMIN(block_w, w-src_x);
-     av_assert2(start_x < end_x && block_w > 0);
-     av_assert2(start_y < end_y && block_h > 0);
-     // fill in the to-be-copied part plus all above/below
-     src += (src_y_add + start_y) * linesize + start_x;
-     buf += start_x;
-     core_fn(buf, src, linesize, start_y, end_y,
-             block_h, start_x, end_x, block_w);
- }
- #if ARCH_X86_32
- static av_noinline void emulated_edge_mc_mmx(uint8_t *buf, const uint8_t *src,
-                                              int linesize,
-                                              int block_w, int block_h,
-                                              int src_x, int src_y, int w, int h)
- {
-     emulated_edge_mc(buf, src, linesize, block_w, block_h, src_x, src_y,
-                      w, h, &ff_emu_edge_core_mmx);
- }
- #endif
- static av_noinline void emulated_edge_mc_sse(uint8_t *buf, const uint8_t *src,
-                                              int linesize,
-                                              int block_w, int block_h,
-                                              int src_x, int src_y, int w, int h)
- {
-     emulated_edge_mc(buf, src, linesize, block_w, block_h, src_x, src_y,
-                      w, h, &ff_emu_edge_core_sse);
- }
- #endif /* HAVE_YASM */
- #if HAVE_INLINE_ASM
 -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)
 +typedef void emulated_edge_mc_func(uint8_t *dst, const uint8_t *src,
 +                                   int linesize, int block_w, int block_h,
 +                                   int src_x, int src_y, int w, int h);
 +
 +static av_always_inline void gmc(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,
 +                                 emulated_edge_mc_func *emu_edge_fn)
  {
      const int w    = 8;
      const int ix   = ox  >> (16 + shift);
          src += 4 - h * stride;
      }
  }
-         width, height, &emulated_edge_mc_mmx);
 +
 +#if HAVE_YASM
 +#if ARCH_X86_32
 +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)
 +{
 +    gmc(dst, src, stride, h, ox, oy, dxx, dxy, dyx, dyy, shift, r,
-         width, height, &emulated_edge_mc_sse);
++        width, height, &ff_emulated_edge_mc_8);
 +}
 +#endif
 +static void gmc_sse(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)
 +{
 +    gmc(dst, src, stride, h, ox, oy, dxx, dxy, dyx, dyy, shift, r,
- #define PREFETCH(name, op)                      \
- static void name(void *mem, int stride, int h)  \
- {                                               \
-     const uint8_t *p = mem;                     \
-     do {                                        \
-         __asm__ volatile (#op" %0" :: "m"(*p)); \
-         p += stride;                            \
-     } while (--h);                              \
- }
- PREFETCH(prefetch_mmxext, prefetcht0)
- PREFETCH(prefetch_3dnow, prefetch)
- #undef PREFETCH
++        width, height, &ff_emulated_edge_mc_8);
 +}
 +#else
 +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)
 +{
 +    gmc(dst, src, stride, h, ox, oy, dxx, dxy, dyx, dyy, shift, r,
 +        width, height, &ff_emulated_edge_mc_8);
 +}
 +#endif
 +
  #endif /* HAVE_INLINE_ASM */
  
  #include "h264_qpel.c"
@@@ -2617,12 -2356,6 +2517,10 @@@ static void dsputil_init_sse(DSPContex
  
      c->scalarproduct_float          = ff_scalarproduct_float_sse;
      c->butterflies_float_interleave = ff_butterflies_float_interleave_sse;
-     if (!high_bit_depth)
-         c->emulated_edge_mc = emulated_edge_mc_sse;
 +
 +#if HAVE_INLINE_ASM
 +    c->gmc = gmc_sse;
 +#endif
  #endif /* HAVE_YASM */
  }
  
index 0000000,07a0324..77f43a6
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,119 +1,126 @@@
 -                                              ptrdiff_t linesize,
+ /*
+  * Copyright (C) 2012 Ronald S. Bultje
+  *
+  * This file is part of Libav.
+  *
+  * Libav 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.
+  *
+  * Libav 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 Libav; if not, write to the Free Software
+  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+  */
+ #include "config.h"
++#include "libavutil/avassert.h"
+ #include "libavutil/common.h"
+ #include "libavutil/cpu.h"
+ #include "libavutil/mem.h"
+ #include "libavutil/x86/asm.h"
+ #include "libavcodec/videodsp.h"
+ #if HAVE_YASM
+ typedef void emu_edge_core_func(uint8_t *buf, const uint8_t *src,
+                                 x86_reg linesize, x86_reg start_y,
+                                 x86_reg end_y, x86_reg block_h,
+                                 x86_reg start_x, x86_reg end_x,
+                                 x86_reg block_w);
+ extern emu_edge_core_func ff_emu_edge_core_mmx;
+ extern emu_edge_core_func ff_emu_edge_core_sse;
+ static av_always_inline void emulated_edge_mc(uint8_t *buf, const uint8_t *src,
 -        src_y_add = h - 1 - src_y;
++                                              ptrdiff_t linesize_arg,
+                                               int block_w, int block_h,
+                                               int src_x, int src_y,
+                                               int w, int h,
+                                               emu_edge_core_func *core_fn)
+ {
+     int start_y, start_x, end_y, end_x, src_y_add = 0;
++    int linesize = linesize_arg;
++
++    if(!w || !h)
++        return;
+     if (src_y >= h) {
 -        src_y_add = 1 - block_h - src_y;
++        src -= src_y*linesize;
++        src_y_add = h - 1;
+         src_y     = h - 1;
+     } else if (src_y <= -block_h) {
 -    assert(start_x < end_x && block_w > 0);
 -    assert(start_y < end_y && block_h > 0);
++        src -= src_y*linesize;
++        src_y_add = 1 - block_h;
+         src_y     = 1 - block_h;
+     }
+     if (src_x >= w) {
+         src   += w - 1 - src_x;
+         src_x  = w - 1;
+     } else if (src_x <= -block_w) {
+         src   += 1 - block_w - src_x;
+         src_x  = 1 - block_w;
+     }
+     start_y = FFMAX(0, -src_y);
+     start_x = FFMAX(0, -src_x);
+     end_y   = FFMIN(block_h, h-src_y);
+     end_x   = FFMIN(block_w, w-src_x);
++    av_assert2(start_x < end_x && block_w > 0);
++    av_assert2(start_y < end_y && block_h > 0);
+     // fill in the to-be-copied part plus all above/below
+     src += (src_y_add + start_y) * linesize + start_x;
+     buf += start_x;
+     core_fn(buf, src, linesize, start_y, end_y,
+             block_h, start_x, end_x, block_w);
+ }
+ #if ARCH_X86_32
+ static av_noinline void emulated_edge_mc_mmx(uint8_t *buf, const uint8_t *src,
+                                              ptrdiff_t linesize,
+                                              int block_w, int block_h,
+                                              int src_x, int src_y, int w, int h)
+ {
+     emulated_edge_mc(buf, src, linesize, block_w, block_h, src_x, src_y,
+                      w, h, &ff_emu_edge_core_mmx);
+ }
+ #endif
+ static av_noinline void emulated_edge_mc_sse(uint8_t *buf, const uint8_t *src,
+                                              ptrdiff_t linesize,
+                                              int block_w, int block_h,
+                                              int src_x, int src_y, int w, int h)
+ {
+     emulated_edge_mc(buf, src, linesize, block_w, block_h, src_x, src_y,
+                      w, h, &ff_emu_edge_core_sse);
+ }
+ #endif /* HAVE_YASM */
+ void ff_prefetch_mmxext(uint8_t *buf, ptrdiff_t stride, int h);
+ void ff_prefetch_3dnow(uint8_t *buf, ptrdiff_t stride, int h);
+ void ff_videodsp_init_x86(VideoDSPContext *ctx, int bpc)
+ {
+ #if HAVE_YASM
+     int mm_flags = av_get_cpu_flags();
+ #if ARCH_X86_32
+     if (bpc <= 8 && mm_flags & AV_CPU_FLAG_MMX) {
+         ctx->emulated_edge_mc = emulated_edge_mc_mmx;
+     }
+     if (mm_flags & AV_CPU_FLAG_3DNOW) {
+         ctx->prefetch = ff_prefetch_3dnow;
+     }
+ #endif /* ARCH_X86_32 */
+     if (mm_flags & AV_CPU_FLAG_MMXEXT) {
+         ctx->prefetch = ff_prefetch_mmxext;
+     }
+     if (bpc <= 8 && mm_flags & AV_CPU_FLAG_SSE) {
+         ctx->emulated_edge_mc = emulated_edge_mc_sse;
+     }
+ #endif /* HAVE_YASM */
+ }