Merge commit '69c25c9284645cf5189af2ede42d6f53828f3b45'
authorMichael Niedermayer <michaelni@gmx.at>
Sat, 26 Jan 2013 13:33:06 +0000 (14:33 +0100)
committerMichael Niedermayer <michaelni@gmx.at>
Sat, 26 Jan 2013 13:33:06 +0000 (14:33 +0100)
* commit '69c25c9284645cf5189af2ede42d6f53828f3b45':
  dnxhdenc: fix invalid reads in dnxhd_mb_var_thread().
  x86: h264qpel: Move stray comment to the right spot and clarify it
  atrac3: use correct loop variable in add_tonal_components()

Conflicts:
tests/ref/vsynth/vsynth1-dnxhd-1080i
tests/ref/vsynth/vsynth2-dnxhd-1080i

Merged-by: Michael Niedermayer <michaelni@gmx.at>
1  2 
libavcodec/dnxhdenc.c
libavcodec/x86/dsputil_mmx.c
libavcodec/x86/h264_qpel.c
tests/ref/vsynth/vsynth1-dnxhd-1080i
tests/ref/vsynth/vsynth2-dnxhd-1080i

diff --combined libavcodec/dnxhdenc.c
@@@ -6,20 -6,20 +6,20 @@@
   * VC-3 encoder funded by the British Broadcasting Corporation
   * 10 bit support added by MirriAd Ltd, Joseph Artsimovich <joseph@mirriad.com>
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * 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.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * 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 Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
@@@ -32,7 -32,6 +32,7 @@@
  #include "internal.h"
  #include "mpegvideo.h"
  #include "dnxhdenc.h"
 +#include "internal.h"
  
  #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
  #define DNX10BIT_QMAT_SHIFT 18 // The largest value that will not lead to overflow for 10bit samples.
@@@ -41,17 -40,11 +41,17 @@@ static const AVOption options[]=
      {"nitris_compat", "encode with Avid Nitris compatibility", offsetof(DNXHDEncContext, nitris_compat), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, VE},
  {NULL}
  };
 -static const AVClass class = { "dnxhd", av_default_item_name, options, LIBAVUTIL_VERSION_INT };
 +
 +static const AVClass class = {
 +    .class_name = "dnxhd",
 +    .item_name  = av_default_item_name,
 +    .option     = options,
 +    .version    = LIBAVUTIL_VERSION_INT,
 +};
  
  #define LAMBDA_FRAC_BITS 10
  
 -static void dnxhd_8bit_get_pixels_8x4_sym(int16_t *restrict block, const uint8_t *pixels, int line_size)
 +static void dnxhd_8bit_get_pixels_8x4_sym(int16_t *av_restrict block, const uint8_t *pixels, int line_size)
  {
      int i;
      for (i = 0; i < 4; i++) {
      memcpy(block + 24, block - 32, sizeof(*block) * 8);
  }
  
 -static av_always_inline void dnxhd_10bit_get_pixels_8x4_sym(int16_t *restrict block, const uint8_t *pixels, int line_size)
 +static av_always_inline void dnxhd_10bit_get_pixels_8x4_sym(int16_t *av_restrict block, const uint8_t *pixels, int line_size)
  {
      int i;
 -
 -    block += 32;
 +    const uint16_t* pixels16 = (const uint16_t*)pixels;
 +    line_size >>= 1;
  
      for (i = 0; i < 4; i++) {
 -        memcpy(block + i     * 8, pixels + i * line_size, 8 * sizeof(*block));
 -        memcpy(block - (i+1) * 8, pixels + i * line_size, 8 * sizeof(*block));
 +        block[0] = pixels16[0]; block[1] = pixels16[1];
 +        block[2] = pixels16[2]; block[3] = pixels16[3];
 +        block[4] = pixels16[4]; block[5] = pixels16[5];
 +        block[6] = pixels16[6]; block[7] = pixels16[7];
 +        pixels16 += line_size;
 +        block += 8;
      }
 +    memcpy(block,      block -  8, sizeof(*block) * 8);
 +    memcpy(block +  8, block - 16, sizeof(*block) * 8);
 +    memcpy(block + 16, block - 24, sizeof(*block) * 8);
 +    memcpy(block + 24, block - 32, sizeof(*block) * 8);
  }
  
  static int dnxhd_10bit_dct_quantize(MpegEncContext *ctx, int16_t *block,
                                      int n, int qscale, int *overflow)
  {
      const uint8_t *scantable= ctx->intra_scantable.scantable;
 -    const int *qmat = ctx->q_intra_matrix[qscale];
 +    const int *qmat = n<4 ? ctx->q_intra_matrix[qscale] : ctx->q_chroma_intra_matrix[qscale];
      int last_non_zero = 0;
      int i;
  
@@@ -137,10 -122,10 +137,10 @@@ static int dnxhd_init_vlc(DNXHDEncConte
                  alevel -= offset<<6;
              }
              for (j = 0; j < 257; j++) {
 -                if (ctx->cid_table->ac_level[j] == alevel &&
 -                    (!offset || (ctx->cid_table->ac_index_flag[j] && offset)) &&
 -                    (!run    || (ctx->cid_table->ac_run_flag  [j] && run))) {
 -                    assert(!ctx->vlc_codes[index]);
 +                if (ctx->cid_table->ac_level[j] >> 1 == alevel &&
 +                    (!offset || (ctx->cid_table->ac_flags[j] & 1) && offset) &&
 +                    (!run    || (ctx->cid_table->ac_flags[j] & 2) && run)) {
 +                    av_assert1(!ctx->vlc_codes[index]);
                      if (alevel) {
                          ctx->vlc_codes[index] = (ctx->cid_table->ac_codes[j]<<1)|(sign&1);
                          ctx->vlc_bits [index] = ctx->cid_table->ac_bits[j]+1;
                      break;
                  }
              }
 -            assert(!alevel || j < 257);
 +            av_assert0(!alevel || j < 257);
              if (offset) {
                  ctx->vlc_codes[index] = (ctx->vlc_codes[index]<<ctx->cid_table->index_bits)|offset;
                  ctx->vlc_bits [index]+= ctx->cid_table->index_bits;
      }
      for (i = 0; i < 62; i++) {
          int run = ctx->cid_table->run[i];
 -        assert(run < 63);
 +        av_assert0(run < 63);
          ctx->run_codes[run] = ctx->cid_table->run_codes[i];
          ctx->run_bits [run] = ctx->cid_table->run_bits[i];
      }
@@@ -223,11 -208,6 +223,11 @@@ static int dnxhd_init_qmat(DNXHDEncCont
          }
      }
  
 +    ctx->m.q_chroma_intra_matrix16 = ctx->qmatrix_c16;
 +    ctx->m.q_chroma_intra_matrix   = ctx->qmatrix_c;
 +    ctx->m.q_intra_matrix16        = ctx->qmatrix_l16;
 +    ctx->m.q_intra_matrix          = ctx->qmatrix_l;
 +
      return 0;
   fail:
      return -1;
@@@ -272,7 -252,6 +272,7 @@@ static int dnxhd_encode_init(AVCodecCon
      av_log(avctx, AV_LOG_DEBUG, "cid %d\n", ctx->cid);
  
      index = ff_dnxhd_get_cid_table(ctx->cid);
 +    av_assert0(index >= 0);
      ctx->cid_table = &ff_dnxhd_cid_table[index];
  
      ctx->m.avctx = avctx;
  
      avctx->bits_per_raw_sample = ctx->cid_table->bit_depth;
  
 -    ff_dsputil_init(&ctx->m.dsp, avctx);
      ff_dct_common_init(&ctx->m);
 +    ff_dct_encode_init(&ctx->m);
 +
      if (!ctx->m.dct_quantize)
          ctx->m.dct_quantize = ff_dct_quantize_c;
  
@@@ -518,8 -496,15 +518,8 @@@ static av_always_inline void dnxhd_get_
  
  static av_always_inline int dnxhd_switch_matrix(DNXHDEncContext *ctx, int i)
  {
 -    if (i&2) {
 -        ctx->m.q_intra_matrix16 = ctx->qmatrix_c16;
 -        ctx->m.q_intra_matrix   = ctx->qmatrix_c;
 -        return 1 + (i&1);
 -    } else {
 -        ctx->m.q_intra_matrix16 = ctx->qmatrix_l16;
 -        ctx->m.q_intra_matrix   = ctx->qmatrix_l;
 -        return 0;
 -    }
 +    const static uint8_t component[8]={0,0,1,2,0,0,1,2};
 +    return component[i];
  }
  
  static int dnxhd_calc_bits_thread(AVCodecContext *avctx, void *arg, int jobnr, int threadnr)
              int n = dnxhd_switch_matrix(ctx, i);
  
              memcpy(block, src_block, 64*sizeof(*block));
 -            last_index = ctx->m.dct_quantize(&ctx->m, block, i, qscale, &overflow);
 +            last_index = ctx->m.dct_quantize(&ctx->m, block, 4&(2*i), qscale, &overflow);
              ac_bits += dnxhd_calc_ac_bits(ctx, block, last_index);
  
              diff = block[0] - ctx->m.last_dc[n];
              if (diff < 0) nbits = av_log2_16bit(-2*diff);
              else          nbits = av_log2_16bit( 2*diff);
  
 -            assert(nbits < ctx->cid_table->bit_depth + 4);
 +            av_assert1(nbits < ctx->cid_table->bit_depth + 4);
              dc_bits += ctx->cid_table->dc_bits[nbits] + nbits;
  
              ctx->m.last_dc[n] = block[0];
@@@ -595,7 -580,8 +595,7 @@@ static int dnxhd_encode_thread(AVCodecC
          for (i = 0; i < 8; i++) {
              int16_t *block = ctx->blocks[i];
              int overflow, n = dnxhd_switch_matrix(ctx, i);
 -            int last_index = ctx->m.dct_quantize(&ctx->m, block, i,
 -                                                 qscale, &overflow);
 +            int last_index = ctx->m.dct_quantize(&ctx->m, block, 4&(2*i), qscale, &overflow);
              //START_TIMER;
              dnxhd_encode_block(ctx, block, last_index, n);
              //STOP_TIMER("encode_block");
@@@ -629,14 -615,35 +629,35 @@@ static void dnxhd_setup_threads_slices(
  static int dnxhd_mb_var_thread(AVCodecContext *avctx, void *arg, int jobnr, int threadnr)
  {
      DNXHDEncContext *ctx = avctx->priv_data;
-     int mb_y = jobnr, mb_x;
+     int mb_y = jobnr, mb_x, x, y;
+     int partial_last_row = (mb_y == ctx->m.mb_height - 1) &&
+                            ((avctx->height >> ctx->interlaced) & 0xF);
      ctx = ctx->thread[threadnr];
      if (ctx->cid_table->bit_depth == 8) {
          uint8_t *pix = ctx->thread[0]->src[0] + ((mb_y<<4) * ctx->m.linesize);
          for (mb_x = 0; mb_x < ctx->m.mb_width; ++mb_x, pix += 16) {
              unsigned mb  = mb_y * ctx->m.mb_width + mb_x;
-             int sum = ctx->m.dsp.pix_sum(pix, ctx->m.linesize);
-             int varc = (ctx->m.dsp.pix_norm1(pix, ctx->m.linesize) - (((unsigned)sum*sum)>>8)+128)>>8;
+             int sum;
+             int varc;
+             if (!partial_last_row && mb_x * 16 <= avctx->width - 16) {
+                 sum  = ctx->m.dsp.pix_sum(pix, ctx->m.linesize);
+                 varc = ctx->m.dsp.pix_norm1(pix, ctx->m.linesize);
+             } else {
+                 int bw = FFMIN(avctx->width - 16 * mb_x, 16);
+                 int bh = FFMIN((avctx->height >> ctx->interlaced) - 16 * mb_y, 16);
+                 sum = varc = 0;
+                 for (y = 0; y < bh; y++) {
+                     for (x = 0; x < bw; x++) {
+                         uint8_t val = pix[x + y * ctx->m.linesize];
+                         sum  += val;
+                         varc += val * val;
+                     }
+                 }
+             }
+             varc = (varc - (((unsigned)sum * sum) >> 8) + 128) >> 8;
              ctx->mb_cmp[mb].value = varc;
              ctx->mb_cmp[mb].mb = mb;
          }
@@@ -824,13 -831,13 +845,13 @@@ static void radix_count(const RCCMPEntr
              buckets[j][get_bucket(v, 0)]++;
              v >>= BUCKET_BITS;
          }
 -        assert(!v);
 +        av_assert1(!v);
      }
      for (j = 0; j < RADIX_PASSES; j++) {
          int offset = size;
          for (i = NBUCKETS - 1; i >= 0; i--)
              buckets[j][i] = offset -= buckets[j][i];
 -        assert(!buckets[j][0]);
 +        av_assert1(!buckets[j][0]);
      }
  }
  
@@@ -924,8 -931,10 +945,8 @@@ static int dnxhd_encode_picture(AVCodec
      int offset, i, ret;
      uint8_t *buf;
  
 -    if ((ret = ff_alloc_packet(pkt, ctx->cid_table->frame_size)) < 0) {
 -        av_log(avctx, AV_LOG_ERROR, "output buffer is too small to compress picture\n");
 +    if ((ret = ff_alloc_packet2(avctx, pkt, ctx->cid_table->frame_size)) < 0)
          return ret;
 -    }
      buf = pkt->data;
  
      dnxhd_load_picture(ctx, frame);
      for (i = 0; i < ctx->m.mb_height; i++) {
          AV_WB32(ctx->msip + i * 4, offset);
          offset += ctx->slice_size[i];
 -        assert(!(ctx->slice_size[i] & 3));
 +        av_assert1(!(ctx->slice_size[i] & 3));
      }
  
      avctx->execute2(avctx, dnxhd_encode_thread, buf, NULL, ctx->m.mb_height);
  
 -    assert(640 + offset + 4 <= ctx->cid_table->coding_unit_size);
 +    av_assert1(640 + offset + 4 <= ctx->cid_table->coding_unit_size);
      memset(buf + 640 + offset, 0, ctx->cid_table->coding_unit_size - 4 - offset - 640);
  
      AV_WB32(buf + ctx->cid_table->coding_unit_size - 4, 0x600DC0DE); // EOF
@@@ -1008,11 -1017,6 +1029,11 @@@ static int dnxhd_encode_end(AVCodecCont
      return 0;
  }
  
 +static const AVCodecDefault dnxhd_defaults[] = {
 +    { "qmax", "1024" }, /* Maximum quantization scale factor allowed for VC-3 */
 +    { NULL },
 +};
 +
  AVCodec ff_dnxhd_encoder = {
      .name           = "dnxhd",
      .type           = AVMEDIA_TYPE_VIDEO,
                                                    AV_PIX_FMT_NONE },
      .long_name      = NULL_IF_CONFIG_SMALL("VC3/DNxHD"),
      .priv_class     = &class,
 +    .defaults       = dnxhd_defaults,
  };
@@@ -3,23 -3,23 +3,23 @@@
   * Copyright (c) 2000, 2001 Fabrice Bellard
   * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
   *
 - * MMX optimization by Nick Kurshev <nickols_k@mail.ru>
 - *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * 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.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * 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 Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + *
 + * MMX optimization by Nick Kurshev <nickols_k@mail.ru>
   */
  
  #include "libavutil/cpu.h"
@@@ -30,7 -30,6 +30,7 @@@
  #include "libavcodec/simple_idct.h"
  #include "dsputil_mmx.h"
  #include "idct_xvid.h"
 +#include "diracdsp_mmx.h"
  
  //#undef NDEBUG
  //#include <assert.h>
@@@ -751,7 -750,7 +751,7 @@@ static void draw_edges_mmx(uint8_t *buf
              : "+r"(ptr)
              : "r"((x86_reg)wrap), "r"((x86_reg)width), "r"(ptr + wrap * height)
              );
 -    } else {
 +    } else if(w==16){
          __asm__ volatile (
              "1:                                 \n\t"
              "movd            (%0), %%mm0        \n\t"
              : "+r"(ptr)
              : "r"((x86_reg)wrap), "r"((x86_reg)width), "r"(ptr + wrap * height)
              );
 +    } else {
 +        av_assert1(w == 4);
 +        __asm__ volatile (
 +            "1:                             \n\t"
 +            "movd            (%0), %%mm0    \n\t"
 +            "punpcklbw      %%mm0, %%mm0    \n\t"
 +            "punpcklwd      %%mm0, %%mm0    \n\t"
 +            "movd           %%mm0, -4(%0)   \n\t"
 +            "movd      -4(%0, %2), %%mm1    \n\t"
 +            "punpcklbw      %%mm1, %%mm1    \n\t"
 +            "punpckhwd      %%mm1, %%mm1    \n\t"
 +            "punpckhdq      %%mm1, %%mm1    \n\t"
 +            "movd           %%mm1, (%0, %2) \n\t"
 +            "add               %1, %0       \n\t"
 +            "cmp               %3, %0       \n\t"
 +            "jb                1b           \n\t"
 +            : "+r"(ptr)
 +            : "r"((x86_reg)wrap), "r"((x86_reg)width), "r"(ptr + wrap * height)
 +            );
      }
  
      /* top and bottom (and hopefully also the corners) */
@@@ -1593,15 -1573,10 +1593,15 @@@ void ff_avg_rv40_qpel16_mc33_mmx(uint8_
    avg_pixels16_xy2_mmx(dst, src, stride, 16);
  }
  
 -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,
 +                                   ptrdiff_t 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);
      const uint16_t dxy4[4] = { dxys, dxys, dxys, dxys };
      const uint16_t dyy4[4] = { dyys, dyys, dyys, dyys };
      const uint64_t shift2 = 2 * shift;
 +#define MAX_STRIDE 4096U
 +#define MAX_H 8U
 +    uint8_t edge_buf[(MAX_H + 1) * MAX_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);
 +    int need_emu =  (unsigned)ix >= width  - w ||
 +                    (unsigned)iy >= height - h;
 +
      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 ||
 -        (unsigned)ix >= width  - w ||
 -        (unsigned)iy >= height - h) {
 +        || (dxx | dxy | dyx | dyy) & 15
 +        || (need_emu && (h > MAX_H || stride > MAX_STRIDE))) {
          // 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);
      }
  
      src += ix + iy * stride;
 +    if (need_emu) {
 +        emu_edge_fn(edge_buf, src, stride, w + 1, h + 1, ix, iy, width, height);
 +        src = edge_buf;
 +    }
  
      __asm__ volatile (
          "movd         %0, %%mm6         \n\t"
          src += 4 - h * stride;
      }
  }
 +
 +#if CONFIG_VIDEODSP
 +#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, &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,
 +        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
 +
  #endif /* HAVE_INLINE_ASM */
  
  void ff_put_pixels16_sse2(uint8_t *block, const uint8_t *pixels,
@@@ -1841,80 -1774,6 +1841,80 @@@ void ff_avg_vc1_mspel_mc00_mmxext(uint8
      avg_pixels8_mmxext(dst, src, stride, 8);
  }
  
 +#if CONFIG_DIRAC_DECODER
 +#define DIRAC_PIXOP(OPNAME, EXT)\
 +void ff_ ## OPNAME ## _dirac_pixels8_ ## EXT(uint8_t *dst, const uint8_t *src[5], int stride, int h)\
 +{\
 +    OPNAME ## _pixels8_ ## EXT(dst, src[0], stride, h);\
 +}\
 +void ff_ ## OPNAME ## _dirac_pixels16_ ## EXT(uint8_t *dst, const uint8_t *src[5], int stride, int h)\
 +{\
 +    OPNAME ## _pixels16_ ## EXT(dst, src[0], stride, h);\
 +}\
 +void ff_ ## OPNAME ## _dirac_pixels32_ ## EXT(uint8_t *dst, const uint8_t *src[5], int stride, int h)\
 +{\
 +    OPNAME ## _pixels16_ ## EXT(dst   , src[0]   , stride, h);\
 +    OPNAME ## _pixels16_ ## EXT(dst+16, src[0]+16, stride, h);\
 +}
 +
 +DIRAC_PIXOP(put, mmx)
 +DIRAC_PIXOP(avg, mmx)
 +DIRAC_PIXOP(avg, mmxext)
 +
 +#if HAVE_YASM
 +void ff_put_dirac_pixels16_sse2(uint8_t *dst, const uint8_t *src[5], int stride, int h)
 +{
 +    ff_put_pixels16_sse2(dst, src[0], stride, h);
 +}
 +void ff_avg_dirac_pixels16_sse2(uint8_t *dst, const uint8_t *src[5], int stride, int h)
 +{
 +    ff_avg_pixels16_sse2(dst, src[0], stride, h);
 +}
 +void ff_put_dirac_pixels32_sse2(uint8_t *dst, const uint8_t *src[5], int stride, int h)
 +{
 +    ff_put_pixels16_sse2(dst   , src[0]   , stride, h);
 +    ff_put_pixels16_sse2(dst+16, src[0]+16, stride, h);
 +}
 +void ff_avg_dirac_pixels32_sse2(uint8_t *dst, const uint8_t *src[5], int stride, int h)
 +{
 +    ff_avg_pixels16_sse2(dst   , src[0]   , stride, h);
 +    ff_avg_pixels16_sse2(dst+16, src[0]+16, stride, h);
 +}
 +#endif
 +#endif
 +
 +/* XXX: Those functions should be suppressed ASAP when all IDCTs are
 + * converted. */
 +#if CONFIG_GPL
 +static void ff_libmpeg2mmx_idct_put(uint8_t *dest, int line_size,
 +                                    int16_t *block)
 +{
 +    ff_mmx_idct(block);
 +    ff_put_pixels_clamped_mmx(block, dest, line_size);
 +}
 +
 +static void ff_libmpeg2mmx_idct_add(uint8_t *dest, int line_size,
 +                                    int16_t *block)
 +{
 +    ff_mmx_idct(block);
 +    ff_add_pixels_clamped_mmx(block, dest, line_size);
 +}
 +
 +static void ff_libmpeg2mmx2_idct_put(uint8_t *dest, int line_size,
 +                                     int16_t *block)
 +{
 +    ff_mmxext_idct(block);
 +    ff_put_pixels_clamped_mmx(block, dest, line_size);
 +}
 +
 +static void ff_libmpeg2mmx2_idct_add(uint8_t *dest, int line_size,
 +                                     int16_t *block)
 +{
 +    ff_mmxext_idct(block);
 +    ff_add_pixels_clamped_mmx(block, dest, line_size);
 +}
 +#endif
 +
  static void vector_clipf_sse(float *dst, const float *src,
                               float min, float max, int len)
  {
@@@ -2047,11 -1906,24 +2047,11 @@@ static void dsputil_init_mmx(DSPContex
          SET_HPEL_FUNCS(put,        [1],  8, mmx);
          SET_HPEL_FUNCS(put_no_rnd, [1],  8, mmx);
          SET_HPEL_FUNCS(avg,        [1],  8, mmx);
 -
 -        switch (avctx->idct_algo) {
 -        case FF_IDCT_AUTO:
 -        case FF_IDCT_SIMPLEMMX:
 -            c->idct_put              = ff_simple_idct_put_mmx;
 -            c->idct_add              = ff_simple_idct_add_mmx;
 -            c->idct                  = ff_simple_idct_mmx;
 -            c->idct_permutation_type = FF_SIMPLE_IDCT_PERM;
 -            break;
 -        case FF_IDCT_XVIDMMX:
 -            c->idct_put              = ff_idct_xvid_mmx_put;
 -            c->idct_add              = ff_idct_xvid_mmx_add;
 -            c->idct                  = ff_idct_xvid_mmx;
 -            break;
 -        }
      }
  
 +#if CONFIG_VIDEODSP && (ARCH_X86_32 || !HAVE_YASM)
      c->gmc = gmc_mmx;
 +#endif
  
      c->add_bytes = add_bytes_mmx;
  
@@@ -2115,6 -1987,12 +2115,6 @@@ static void dsputil_init_mmxext(DSPCont
          }
      }
  
 -    if (!high_bit_depth && avctx->idct_algo == FF_IDCT_XVIDMMX) {
 -        c->idct_put = ff_idct_xvid_mmxext_put;
 -        c->idct_add = ff_idct_xvid_mmxext_add;
 -        c->idct     = ff_idct_xvid_mmxext;
 -    }
 -
      if (CONFIG_VP3_DECODER && (avctx->codec_id == AV_CODEC_ID_VP3 ||
                                 avctx->codec_id == AV_CODEC_ID_THEORA)) {
          c->put_no_rnd_pixels_tab[1][1] = put_no_rnd_pixels8_x2_exact_mmxext;
@@@ -2213,12 -2091,6 +2213,12 @@@ static void dsputil_init_sse(DSPContex
  
      c->vector_clipf = vector_clipf_sse;
  #endif /* HAVE_INLINE_ASM */
 +
 +#if HAVE_YASM
 +#if HAVE_INLINE_ASM && CONFIG_VIDEODSP
 +    c->gmc = gmc_sse;
 +#endif
 +#endif /* HAVE_YASM */
  }
  
  static void dsputil_init_sse2(DSPContext *c, AVCodecContext *avctx,
@@@ -2309,8 -2181,6 +2309,6 @@@ static void dsputil_init_avx(DSPContex
      const int bit_depth = avctx->bits_per_raw_sample;
  
      if (bit_depth == 10) {
-         // AVX implies !cache64.
-         // TODO: Port cache(32|64) detection from x264.
          if (CONFIG_H264CHROMA) {
              c->put_h264_chroma_pixels_tab[0] = ff_put_h264_chroma_mc8_10_avx;
              c->avg_h264_chroma_pixels_tab[0] = ff_avg_h264_chroma_mc8_10_avx;
@@@ -2328,50 -2198,8 +2326,50 @@@ void ff_dsputil_init_mmx(DSPContext *c
          c->add_hfyu_median_prediction = add_hfyu_median_prediction_cmov;
  #endif
  
 -    if (mm_flags & AV_CPU_FLAG_MMX)
 +    if (mm_flags & AV_CPU_FLAG_MMX) {
 +#if HAVE_INLINE_ASM
 +        const int idct_algo = avctx->idct_algo;
 +
 +        if (avctx->lowres == 0 && avctx->bits_per_raw_sample <= 8) {
 +            if (idct_algo == FF_IDCT_AUTO || idct_algo == FF_IDCT_SIMPLEMMX) {
 +                c->idct_put              = ff_simple_idct_put_mmx;
 +                c->idct_add              = ff_simple_idct_add_mmx;
 +                c->idct                  = ff_simple_idct_mmx;
 +                c->idct_permutation_type = FF_SIMPLE_IDCT_PERM;
 +#if CONFIG_GPL
 +            } else if (idct_algo == FF_IDCT_LIBMPEG2MMX) {
 +                if (mm_flags & AV_CPU_FLAG_MMX2) {
 +                    c->idct_put = ff_libmpeg2mmx2_idct_put;
 +                    c->idct_add = ff_libmpeg2mmx2_idct_add;
 +                    c->idct     = ff_mmxext_idct;
 +                } else {
 +                    c->idct_put = ff_libmpeg2mmx_idct_put;
 +                    c->idct_add = ff_libmpeg2mmx_idct_add;
 +                    c->idct     = ff_mmx_idct;
 +                }
 +                c->idct_permutation_type = FF_LIBMPEG2_IDCT_PERM;
 +#endif
 +            } else if (idct_algo == FF_IDCT_XVIDMMX) {
 +                if (mm_flags & AV_CPU_FLAG_SSE2) {
 +                    c->idct_put              = ff_idct_xvid_sse2_put;
 +                    c->idct_add              = ff_idct_xvid_sse2_add;
 +                    c->idct                  = ff_idct_xvid_sse2;
 +                    c->idct_permutation_type = FF_SSE2_IDCT_PERM;
 +                } else if (mm_flags & AV_CPU_FLAG_MMXEXT) {
 +                    c->idct_put              = ff_idct_xvid_mmxext_put;
 +                    c->idct_add              = ff_idct_xvid_mmxext_add;
 +                    c->idct                  = ff_idct_xvid_mmxext;
 +                } else {
 +                    c->idct_put              = ff_idct_xvid_mmx_put;
 +                    c->idct_add              = ff_idct_xvid_mmx_add;
 +                    c->idct                  = ff_idct_xvid_mmx;
 +                }
 +            }
 +        }
 +#endif /* HAVE_INLINE_ASM */
 +
          dsputil_init_mmx(c, avctx, mm_flags);
 +    }
  
      if (mm_flags & AV_CPU_FLAG_MMXEXT)
          dsputil_init_mmxext(c, avctx, mm_flags);
@@@ -2,20 -2,20 +2,20 @@@
   * Copyright (c) 2004-2005 Michael Niedermayer, Loren Merritt
   * Copyright (c) 2011 Daniel Kang
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * 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.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * 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 Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
@@@ -611,6 -611,10 +611,10 @@@ void ff_h264qpel_init_x86(H264QpelConte
      }
  
      if (EXTERNAL_AVX(mm_flags)) {
+         /* AVX implies 64 byte cache lines without the need to avoid unaligned
+          * memory accesses that cross the boundary between two cache lines.
+          * TODO: Port X264_CPU_CACHELINE_32/64 detection from x264 to avoid
+          * having to treat SSE2 functions with such properties as AVX. */
          if (bit_depth == 10) {
              H264_QPEL_FUNCS_10(1, 0, sse2);
              H264_QPEL_FUNCS_10(2, 0, sse2);
@@@ -1,4 -1,4 +1,4 @@@
- 9a4781b0a052d9efaafbaf8893db9632 *tests/data/fate/vsynth1-dnxhd-1080i.mov
 -2412f206f5efcbbcc3f2bba0c86b73d4 *tests/data/fate/vsynth1-dnxhd-1080i.mov
 -3031875 tests/data/fate/vsynth1-dnxhd-1080i.mov
 -34076f61254997c8157eafed1c916472 *tests/data/fate/vsynth1-dnxhd-1080i.out.rawvideo
++124c991ee3ac0caef39a58a45287a762 *tests/data/fate/vsynth1-dnxhd-1080i.mov
 +3031911 tests/data/fate/vsynth1-dnxhd-1080i.mov
- e55bf857297ba4d911a9d17a984b125d *tests/data/fate/vsynth1-dnxhd-1080i.out.rawvideo
++a09132c6db44f415e831dcaa630a351b *tests/data/fate/vsynth1-dnxhd-1080i.out.rawvideo
  stddev:    6.29 PSNR: 32.15 MAXDIFF:   64 bytes:  7603200/   760320
@@@ -1,4 -1,4 +1,4 @@@
- 93b878dcf8f2ecc9798d0e0885c9eec9 *tests/data/fate/vsynth2-dnxhd-1080i.mov
 -65ca6385b565b6ea9a2e28150eef1d46 *tests/data/fate/vsynth2-dnxhd-1080i.mov
 -3031875 tests/data/fate/vsynth2-dnxhd-1080i.mov
 -42262a2325441b38b3b3c8a42d888e7d *tests/data/fate/vsynth2-dnxhd-1080i.out.rawvideo
++5d7ab75ce6e547ed63a7a0eacf18f078 *tests/data/fate/vsynth2-dnxhd-1080i.mov
 +3031911 tests/data/fate/vsynth2-dnxhd-1080i.mov
- 27edc8dfe2ca19097c7f9119705b3a60 *tests/data/fate/vsynth2-dnxhd-1080i.out.rawvideo
++744ba46da5d4c19a28562ea31061d170 *tests/data/fate/vsynth2-dnxhd-1080i.out.rawvideo
  stddev:    1.31 PSNR: 45.77 MAXDIFF:   23 bytes:  7603200/   760320