Merge remote-tracking branch 'qatar/master'
authorMichael Niedermayer <michaelni@gmx.at>
Sat, 4 Jun 2011 04:31:35 +0000 (06:31 +0200)
committerMichael Niedermayer <michaelni@gmx.at>
Sat, 4 Jun 2011 04:35:17 +0000 (06:35 +0200)
* qatar/master: (21 commits)
  build: simplify commands for clean target
  swscale: split swscale.c in unscaled and generic conversion routines.
  swscale: cosmetics.
  swscale: integrate (literally) swscale_template.c in swscale.c.
  swscale: split out x86/swscale_template.c from swscale.c.
  swscale: enable hScale_altivec_real.
  swscale: split out ppc _template.c files from main swscale.c.
  swscale: remove indirections in ppc/swscale_template.c.
  swscale: split out unscaled altivec YUV converters in their own file.
  mpegvideoenc: fix multislice fate tests with threading disabled.
  mpegts: Wrap #ifdef DEBUG and av_hex_dump_log() combination in a macro.
  build: Simplify texi2html invocation through the --output option.
  Mark some variables with av_unused
  Replace avcodec_get_pix_fmt_name() by av_get_pix_fmt_name().
  svq3: Check negative mb_type to fix potential crash.
  svq3: Move svq3-specific fields to their own context.
  rawdec: initialize return value to 0.
  Remove unused get_psnr() prototype
  rawdec: don't leak option strings.
  bktr: get default framerate from video standard.
  ...

Merged-by: Michael Niedermayer <michaelni@gmx.at>
32 files changed:
1  2 
Makefile
ffmpeg.c
libavcodec/dsputil.h
libavcodec/dv.c
libavcodec/flacenc.c
libavcodec/mpegvideo.c
libavcodec/mpegvideo_enc.c
libavcodec/svq3.c
libavcodec/targaenc.c
libavcodec/utils.c
libavcodec/wmaprodec.c
libavdevice/bktr.c
libavdevice/libdc1394.c
libavformat/internal.h
libavformat/mov.c
libavformat/mpegts.c
libavformat/nsvdec.c
libavformat/r3d.c
libavformat/rawdec.c
libavformat/rtpdec.c
libavformat/utils.c
libswscale/ppc/swscale_altivec.c
libswscale/ppc/yuv2rgb_altivec.c
libswscale/ppc/yuv2rgb_altivec.h
libswscale/ppc/yuv2yuv_altivec.c
libswscale/swscale.c
libswscale/swscale_internal.h
libswscale/swscale_template.c
libswscale/swscale_unscaled.c
libswscale/x86/swscale_mmx.c
libswscale/x86/swscale_template.c
subdir.mak

diff --cc Makefile
Simple merge
diff --cc ffmpeg.c
+++ b/ffmpeg.c
@@@ -1208,34 -1171,26 +1208,34 @@@ static void do_video_out(AVFormatContex
          av_log(NULL, AV_LOG_INFO,
                 "Input stream #%d.%d frame changed from size:%dx%d fmt:%s to size:%dx%d fmt:%s\n",
                 ist->file_index, ist->st->index,
-                ost->resample_width, ost->resample_height, avcodec_get_pix_fmt_name(ost->resample_pix_fmt),
-                dec->width         , dec->height         , avcodec_get_pix_fmt_name(dec->pix_fmt));
+                ost->resample_width, ost->resample_height, av_get_pix_fmt_name(ost->resample_pix_fmt),
+                dec->width         , dec->height         , av_get_pix_fmt_name(dec->pix_fmt));
 -        if(!ost->video_resample)
 -            ffmpeg_exit(1);
 +        ost->resample_width   = dec->width;
 +        ost->resample_height  = dec->height;
 +        ost->resample_pix_fmt = dec->pix_fmt;
      }
  
 -#if !CONFIG_AVFILTER
 +    ost->video_resample = dec->width   != enc->width  ||
 +                          dec->height  != enc->height ||
 +                          dec->pix_fmt != enc->pix_fmt;
 +
      if (ost->video_resample) {
 -        final_picture = &ost->pict_tmp;
 -        if (resample_changed) {
 +        final_picture = &ost->resample_frame;
 +        if (!ost->img_resample_ctx || resample_changed) {
 +            /* initialize the destination picture */
 +            if (!ost->resample_frame.data[0]) {
 +                avcodec_get_frame_defaults(&ost->resample_frame);
 +                if (avpicture_alloc((AVPicture *)&ost->resample_frame, enc->pix_fmt,
 +                                    enc->width, enc->height)) {
 +                    fprintf(stderr, "Cannot allocate temp picture, check pix fmt\n");
 +                    ffmpeg_exit(1);
 +                }
 +            }
              /* initialize a new scaler context */
              sws_freeContext(ost->img_resample_ctx);
 -            ost->img_resample_ctx = sws_getContext(
 -                ist->st->codec->width,
 -                ist->st->codec->height,
 -                ist->st->codec->pix_fmt,
 -                ost->st->codec->width,
 -                ost->st->codec->height,
 -                ost->st->codec->pix_fmt,
 -                ost->sws_flags, NULL, NULL, NULL);
 +            ost->img_resample_ctx = sws_getContext(dec->width, dec->height, dec->pix_fmt,
 +                                                   enc->width, enc->height, enc->pix_fmt,
 +                                                   ost->sws_flags, NULL, NULL, NULL);
              if (ost->img_resample_ctx == NULL) {
                  fprintf(stderr, "Cannot get resampling context\n");
                  ffmpeg_exit(1);
Simple merge
diff --cc libavcodec/dv.c
Simple merge
Simple merge
@@@ -746,7 -749,8 +745,7 @@@ av_cold int MPV_common_init(MpegEncCont
      s->context_initialized = 1;
      s->thread_context[0]= s;
  
-     if (HAVE_THREADS && s->avctx->active_thread_type&FF_THREAD_SLICE) {
 -    if (s->width && s->height) {
+     if (s->encoding || (HAVE_THREADS && s->avctx->active_thread_type&FF_THREAD_SLICE)) {
          threads = s->avctx->thread_count;
  
          for(i=1; i<threads; i++){
Simple merge
@@@ -821,10 -819,10 +821,11 @@@ static av_cold int svq3_decode_init(AVC
      if (!s->context_initialized) {
          h->chroma_qp[0] = h->chroma_qp[1] = 4;
  
-         svq3->halfpel_flag = 1;
+         svq3->halfpel_flag  = 1;
          svq3->thirdpel_flag = 1;
-         svq3->unknown_flag = 0;
+         svq3->unknown_flag  = 0;
 +
          /* prowl for the "SEQH" marker in the extradata */
          extradata = (unsigned char *)avctx->extradata;
          for (m = 0; m < avctx->extradata_size; m++) {
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -1149,12 -1131,10 +1147,11 @@@ static void pat_cb(MpegTSFilter *filter
      SectionHeader h1, *h = &h1;
      const uint8_t *p, *p_end;
      int sid, pmt_pid;
 +    AVProgram *program;
  
- #ifdef DEBUG
      av_dlog(ts->stream, "PAT:\n");
-     av_hex_dump_log(ts->stream, AV_LOG_DEBUG, (uint8_t *)section, section_len);
- #endif
+     hex_dump_debug(ts->stream, (uint8_t *)section, section_len);
      p_end = section + section_len - 4;
      p = section;
      if (parse_section_header(h, &p, p_end) < 0)
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -2016,22 -1980,20 +2016,22 @@@ static void av_estimate_timings(AVForma
      }
      av_update_stream_timings(ic);
  
 +#if 0
      {
          int i;
-         AVStream *st;
+         AVStream av_unused *st;
          for(i = 0;i < ic->nb_streams; i++) {
              st = ic->streams[i];
 -            av_dlog(ic, "%d: start_time: %0.3f duration: %0.3f\n", i,
 -                    (double) st->start_time / AV_TIME_BASE,
 -                    (double) st->duration   / AV_TIME_BASE);
 +        printf("%d: start_time: %0.3f duration: %0.3f\n",
 +               i, (double)st->start_time / AV_TIME_BASE,
 +               (double)st->duration / AV_TIME_BASE);
          }
 -        av_dlog(ic, "stream: start_time: %0.3f duration: %0.3f bitrate=%d kb/s\n",
 -                (double) ic->start_time / AV_TIME_BASE,
 -                (double) ic->duration   / AV_TIME_BASE,
 -                ic->bit_rate / 1000);
 +        printf("stream: start_time: %0.3f duration: %0.3f bitrate=%d kb/s\n",
 +               (double)ic->start_time / AV_TIME_BASE,
 +               (double)ic->duration / AV_TIME_BASE,
 +               ic->bit_rate / 1000);
      }
 +#endif
  }
  
  static int has_codec_parameters(AVCodecContext *enc)
Simple merge
@@@ -95,7 -95,7 +95,8 @@@ adjustment
  #include "libswscale/swscale.h"
  #include "libswscale/swscale_internal.h"
  #include "libavutil/cpu.h"
 +#include "libavutil/pixdesc.h"
+ #include "yuv2rgb_altivec.h"
  
  #undef PROFILE_THE_BEAST
  #undef INC_SCALING
index 0000000,b54a856..15385b1
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,34 +1,34 @@@
 - * This file is part of Libav.
+ /*
+  * AltiVec-enhanced yuv2yuvX
+  *
+  * Copyright (C) 2004 Romain Dolbeau <romain@dolbeau.org>
+  * based on the equivalent C code in swscale.c
+  *
 - * Libav is free software; you can redistribute it and/or
++ * This file is part of FFmpeg.
+  *
 - * Libav is distributed in the hope that it will be useful,
++ * 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.
+  *
 - * License along with Libav; if not, write to the Free Software
++ * 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 FFmpeg; if not, write to the Free Software
+  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+  */
+ #ifndef PPC_YUV2RGB_ALTIVEC_H
+ #define PPC_YUV2RGB_ALTIVEC_H 1
+ void ff_yuv2packedX_altivec(SwsContext *c, const int16_t *lumFilter,
+                             const int16_t **lumSrc, int lumFilterSize,
+                             const int16_t *chrFilter, const int16_t **chrUSrc,
+                             const int16_t **chrVSrc, int chrFilterSize,
+                             const int16_t **alpSrc, uint8_t *dest,
+                             int dstW, int dstY);
+ #endif /* PPC_YUV2RGB_ALTIVEC_H */
index 0000000,4cd02ff..82c265a
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,191 +1,191 @@@
 - * This file is part of Libav.
+ /*
+  * AltiVec-enhanced yuv-to-yuv convertion routines.
+  *
+  * Copyright (C) 2004 Romain Dolbeau <romain@dolbeau.org>
+  * based on the equivalent C code in swscale.c
+  *
 - * Libav is free software; you can redistribute it and/or
++ * This file is part of FFmpeg.
+  *
 - * Libav is distributed in the hope that it will be useful,
++ * 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.
+  *
 - * License along with Libav; if not, write to the Free Software
++ * 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 FFmpeg; if not, write to the Free Software
+  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+  */
+ #include <inttypes.h>
+ #include "config.h"
+ #include "libswscale/swscale.h"
+ #include "libswscale/swscale_internal.h"
+ #include "libavutil/cpu.h"
+ static int yv12toyuy2_unscaled_altivec(SwsContext *c, const uint8_t* src[],
+                                        int srcStride[], int srcSliceY,
+                                        int srcSliceH, uint8_t* dstParam[],
+                                        int dstStride_a[])
+ {
+     uint8_t *dst=dstParam[0] + dstStride_a[0]*srcSliceY;
+     // yv12toyuy2(src[0], src[1], src[2], dst, c->srcW, srcSliceH, srcStride[0], srcStride[1], dstStride[0]);
+     const uint8_t *ysrc = src[0];
+     const uint8_t *usrc = src[1];
+     const uint8_t *vsrc = src[2];
+     const int width = c->srcW;
+     const int height = srcSliceH;
+     const int lumStride = srcStride[0];
+     const int chromStride = srcStride[1];
+     const int dstStride = dstStride_a[0];
+     const vector unsigned char yperm = vec_lvsl(0, ysrc);
+     const int vertLumPerChroma = 2;
+     register unsigned int y;
+     /* This code assumes:
+     1) dst is 16 bytes-aligned
+     2) dstStride is a multiple of 16
+     3) width is a multiple of 16
+     4) lum & chrom stride are multiples of 8
+     */
+     for (y=0; y<height; y++) {
+         int i;
+         for (i = 0; i < width - 31; i+= 32) {
+             const unsigned int j = i >> 1;
+             vector unsigned char v_yA = vec_ld(i, ysrc);
+             vector unsigned char v_yB = vec_ld(i + 16, ysrc);
+             vector unsigned char v_yC = vec_ld(i + 32, ysrc);
+             vector unsigned char v_y1 = vec_perm(v_yA, v_yB, yperm);
+             vector unsigned char v_y2 = vec_perm(v_yB, v_yC, yperm);
+             vector unsigned char v_uA = vec_ld(j, usrc);
+             vector unsigned char v_uB = vec_ld(j + 16, usrc);
+             vector unsigned char v_u = vec_perm(v_uA, v_uB, vec_lvsl(j, usrc));
+             vector unsigned char v_vA = vec_ld(j, vsrc);
+             vector unsigned char v_vB = vec_ld(j + 16, vsrc);
+             vector unsigned char v_v = vec_perm(v_vA, v_vB, vec_lvsl(j, vsrc));
+             vector unsigned char v_uv_a = vec_mergeh(v_u, v_v);
+             vector unsigned char v_uv_b = vec_mergel(v_u, v_v);
+             vector unsigned char v_yuy2_0 = vec_mergeh(v_y1, v_uv_a);
+             vector unsigned char v_yuy2_1 = vec_mergel(v_y1, v_uv_a);
+             vector unsigned char v_yuy2_2 = vec_mergeh(v_y2, v_uv_b);
+             vector unsigned char v_yuy2_3 = vec_mergel(v_y2, v_uv_b);
+             vec_st(v_yuy2_0, (i << 1), dst);
+             vec_st(v_yuy2_1, (i << 1) + 16, dst);
+             vec_st(v_yuy2_2, (i << 1) + 32, dst);
+             vec_st(v_yuy2_3, (i << 1) + 48, dst);
+         }
+         if (i < width) {
+             const unsigned int j = i >> 1;
+             vector unsigned char v_y1 = vec_ld(i, ysrc);
+             vector unsigned char v_u = vec_ld(j, usrc);
+             vector unsigned char v_v = vec_ld(j, vsrc);
+             vector unsigned char v_uv_a = vec_mergeh(v_u, v_v);
+             vector unsigned char v_yuy2_0 = vec_mergeh(v_y1, v_uv_a);
+             vector unsigned char v_yuy2_1 = vec_mergel(v_y1, v_uv_a);
+             vec_st(v_yuy2_0, (i << 1), dst);
+             vec_st(v_yuy2_1, (i << 1) + 16, dst);
+         }
+         if ((y&(vertLumPerChroma-1)) == vertLumPerChroma-1) {
+             usrc += chromStride;
+             vsrc += chromStride;
+         }
+         ysrc += lumStride;
+         dst += dstStride;
+     }
+     return srcSliceH;
+ }
+ static int yv12touyvy_unscaled_altivec(SwsContext *c, const uint8_t* src[],
+                                        int srcStride[], int srcSliceY,
+                                        int srcSliceH, uint8_t* dstParam[],
+                                        int dstStride_a[])
+ {
+     uint8_t *dst=dstParam[0] + dstStride_a[0]*srcSliceY;
+     // yv12toyuy2(src[0], src[1], src[2], dst, c->srcW, srcSliceH, srcStride[0], srcStride[1], dstStride[0]);
+     const uint8_t *ysrc = src[0];
+     const uint8_t *usrc = src[1];
+     const uint8_t *vsrc = src[2];
+     const int width = c->srcW;
+     const int height = srcSliceH;
+     const int lumStride = srcStride[0];
+     const int chromStride = srcStride[1];
+     const int dstStride = dstStride_a[0];
+     const int vertLumPerChroma = 2;
+     const vector unsigned char yperm = vec_lvsl(0, ysrc);
+     register unsigned int y;
+     /* This code assumes:
+     1) dst is 16 bytes-aligned
+     2) dstStride is a multiple of 16
+     3) width is a multiple of 16
+     4) lum & chrom stride are multiples of 8
+     */
+     for (y=0; y<height; y++) {
+         int i;
+         for (i = 0; i < width - 31; i+= 32) {
+             const unsigned int j = i >> 1;
+             vector unsigned char v_yA = vec_ld(i, ysrc);
+             vector unsigned char v_yB = vec_ld(i + 16, ysrc);
+             vector unsigned char v_yC = vec_ld(i + 32, ysrc);
+             vector unsigned char v_y1 = vec_perm(v_yA, v_yB, yperm);
+             vector unsigned char v_y2 = vec_perm(v_yB, v_yC, yperm);
+             vector unsigned char v_uA = vec_ld(j, usrc);
+             vector unsigned char v_uB = vec_ld(j + 16, usrc);
+             vector unsigned char v_u = vec_perm(v_uA, v_uB, vec_lvsl(j, usrc));
+             vector unsigned char v_vA = vec_ld(j, vsrc);
+             vector unsigned char v_vB = vec_ld(j + 16, vsrc);
+             vector unsigned char v_v = vec_perm(v_vA, v_vB, vec_lvsl(j, vsrc));
+             vector unsigned char v_uv_a = vec_mergeh(v_u, v_v);
+             vector unsigned char v_uv_b = vec_mergel(v_u, v_v);
+             vector unsigned char v_uyvy_0 = vec_mergeh(v_uv_a, v_y1);
+             vector unsigned char v_uyvy_1 = vec_mergel(v_uv_a, v_y1);
+             vector unsigned char v_uyvy_2 = vec_mergeh(v_uv_b, v_y2);
+             vector unsigned char v_uyvy_3 = vec_mergel(v_uv_b, v_y2);
+             vec_st(v_uyvy_0, (i << 1), dst);
+             vec_st(v_uyvy_1, (i << 1) + 16, dst);
+             vec_st(v_uyvy_2, (i << 1) + 32, dst);
+             vec_st(v_uyvy_3, (i << 1) + 48, dst);
+         }
+         if (i < width) {
+             const unsigned int j = i >> 1;
+             vector unsigned char v_y1 = vec_ld(i, ysrc);
+             vector unsigned char v_u = vec_ld(j, usrc);
+             vector unsigned char v_v = vec_ld(j, vsrc);
+             vector unsigned char v_uv_a = vec_mergeh(v_u, v_v);
+             vector unsigned char v_uyvy_0 = vec_mergeh(v_uv_a, v_y1);
+             vector unsigned char v_uyvy_1 = vec_mergel(v_uv_a, v_y1);
+             vec_st(v_uyvy_0, (i << 1), dst);
+             vec_st(v_uyvy_1, (i << 1) + 16, dst);
+         }
+         if ((y&(vertLumPerChroma-1)) == vertLumPerChroma-1) {
+             usrc += chromStride;
+             vsrc += chromStride;
+         }
+         ysrc += lumStride;
+         dst += dstStride;
+     }
+     return srcSliceH;
+ }
+ void ff_swscale_get_unscaled_altivec(SwsContext *c)
+ {
+     if ((av_get_cpu_flags() & AV_CPU_FLAG_ALTIVEC) && !(c->srcW & 15) &&
+         !(c->flags & SWS_BITEXACT) && c->srcFormat == PIX_FMT_YUV420P) {
+         enum PixelFormat dstFormat = c->dstFormat;
+         // unscaled YV12 -> packed YUV, we want speed
+         if (dstFormat == PIX_FMT_YUYV422)
+             c->swScale= yv12toyuy2_unscaled_altivec;
+         else if (dstFormat == PIX_FMT_UYVY422)
+             c->swScale= yv12touyvy_unscaled_altivec;
+     }
+ }
@@@ -60,27 -60,14 +60,14 @@@ untested special converter
  #include "swscale.h"
  #include "swscale_internal.h"
  #include "rgb2rgb.h"
 +#include "libavutil/avassert.h"
  #include "libavutil/intreadwrite.h"
- #include "libavutil/x86_cpu.h"
  #include "libavutil/cpu.h"
  #include "libavutil/avutil.h"
  #include "libavutil/mathematics.h"
  #include "libavutil/bswap.h"
  #include "libavutil/pixdesc.h"
  
- #undef MOVNTQ
- #undef PAVGB
--#define DITHER1XBPP
- #define isPacked(x)         (       \
-            (x)==PIX_FMT_PAL8        \
-         || (x)==PIX_FMT_YUYV422     \
-         || (x)==PIX_FMT_UYVY422     \
-         || (x)==PIX_FMT_GRAY8A       \
-         || isAnyRGB(x)              \
-     )
  
  #define RGB2YUV_SHIFT 15
  #define BY ( (int)(0.114*219/255*(1<<RGB2YUV_SHIFT)+0.5))
@@@ -207,106 -194,14 +194,109 @@@ DECLARE_ALIGNED(8, const uint8_t, dithe
  };
  #endif
  
- static av_always_inline void yuv2yuvX16inC_template(const int16_t *lumFilter, const int16_t **lumSrc, int lumFilterSize,
-                                                     const int16_t *chrFilter, const int16_t **chrUSrc,
-                                                     const int16_t **chrVSrc, int chrFilterSize,
-                                                     const int16_t **alpSrc, uint16_t *dest, uint16_t *uDest, uint16_t *vDest, uint16_t *aDest,
-                                                     int dstW, int chrDstW, int big_endian, int output_bits)
 +DECLARE_ALIGNED(8, const uint8_t, dithers)[8][8][8]={
 +{
 +  {   0,  1,  0,  1,  0,  1,  0,  1,},
 +  {   1,  0,  1,  0,  1,  0,  1,  0,},
 +  {   0,  1,  0,  1,  0,  1,  0,  1,},
 +  {   1,  0,  1,  0,  1,  0,  1,  0,},
 +  {   0,  1,  0,  1,  0,  1,  0,  1,},
 +  {   1,  0,  1,  0,  1,  0,  1,  0,},
 +  {   0,  1,  0,  1,  0,  1,  0,  1,},
 +  {   1,  0,  1,  0,  1,  0,  1,  0,},
 +},{
 +  {   1,  2,  1,  2,  1,  2,  1,  2,},
 +  {   3,  0,  3,  0,  3,  0,  3,  0,},
 +  {   1,  2,  1,  2,  1,  2,  1,  2,},
 +  {   3,  0,  3,  0,  3,  0,  3,  0,},
 +  {   1,  2,  1,  2,  1,  2,  1,  2,},
 +  {   3,  0,  3,  0,  3,  0,  3,  0,},
 +  {   1,  2,  1,  2,  1,  2,  1,  2,},
 +  {   3,  0,  3,  0,  3,  0,  3,  0,},
 +},{
 +  {   2,  4,  3,  5,  2,  4,  3,  5,},
 +  {   6,  0,  7,  1,  6,  0,  7,  1,},
 +  {   3,  5,  2,  4,  3,  5,  2,  4,},
 +  {   7,  1,  6,  0,  7,  1,  6,  0,},
 +  {   2,  4,  3,  5,  2,  4,  3,  5,},
 +  {   6,  0,  7,  1,  6,  0,  7,  1,},
 +  {   3,  5,  2,  4,  3,  5,  2,  4,},
 +  {   7,  1,  6,  0,  7,  1,  6,  0,},
 +},{
 +  {   4,  8,  7, 11,  4,  8,  7, 11,},
 +  {  12,  0, 15,  3, 12,  0, 15,  3,},
 +  {   6, 10,  5,  9,  6, 10,  5,  9,},
 +  {  14,  2, 13,  1, 14,  2, 13,  1,},
 +  {   4,  8,  7, 11,  4,  8,  7, 11,},
 +  {  12,  0, 15,  3, 12,  0, 15,  3,},
 +  {   6, 10,  5,  9,  6, 10,  5,  9,},
 +  {  14,  2, 13,  1, 14,  2, 13,  1,},
 +},{
 +  {   9, 17, 15, 23,  8, 16, 14, 22,},
 +  {  25,  1, 31,  7, 24,  0, 30,  6,},
 +  {  13, 21, 11, 19, 12, 20, 10, 18,},
 +  {  29,  5, 27,  3, 28,  4, 26,  2,},
 +  {   8, 16, 14, 22,  9, 17, 15, 23,},
 +  {  24,  0, 30,  6, 25,  1, 31,  7,},
 +  {  12, 20, 10, 18, 13, 21, 11, 19,},
 +  {  28,  4, 26,  2, 29,  5, 27,  3,},
 +},{
 +  {  18, 34, 30, 46, 17, 33, 29, 45,},
 +  {  50,  2, 62, 14, 49,  1, 61, 13,},
 +  {  26, 42, 22, 38, 25, 41, 21, 37,},
 +  {  58, 10, 54,  6, 57,  9, 53,  5,},
 +  {  16, 32, 28, 44, 19, 35, 31, 47,},
 +  {  48,  0, 60, 12, 51,  3, 63, 15,},
 +  {  24, 40, 20, 36, 27, 43, 23, 39,},
 +  {  56,  8, 52,  4, 59, 11, 55,  7,},
 +},{
 +  {  18, 34, 30, 46, 17, 33, 29, 45,},
 +  {  50,  2, 62, 14, 49,  1, 61, 13,},
 +  {  26, 42, 22, 38, 25, 41, 21, 37,},
 +  {  58, 10, 54,  6, 57,  9, 53,  5,},
 +  {  16, 32, 28, 44, 19, 35, 31, 47,},
 +  {  48,  0, 60, 12, 51,  3, 63, 15,},
 +  {  24, 40, 20, 36, 27, 43, 23, 39,},
 +  {  56,  8, 52,  4, 59, 11, 55,  7,},
 +},{
 +  {  36, 68, 60, 92, 34, 66, 58, 90,},
 +  { 100,  4,124, 28, 98,  2,122, 26,},
 +  {  52, 84, 44, 76, 50, 82, 42, 74,},
 +  { 116, 20,108, 12,114, 18,106, 10,},
 +  {  32, 64, 56, 88, 38, 70, 62, 94,},
 +  {  96,  0,120, 24,102,  6,126, 30,},
 +  {  48, 80, 40, 72, 54, 86, 46, 78,},
 +  { 112, 16,104,  8,118, 22,110, 14,},
 +}};
 +
 +static const uint8_t flat64[8]={64,64,64,64,64,64,64,64};
 +
 +uint16_t dither_scale[15][16]={
 +{    2,    3,    3,    5,    5,    5,    5,    5,    5,    5,    5,    5,    5,    5,    5,    5,},
 +{    2,    3,    7,    7,   13,   13,   25,   25,   25,   25,   25,   25,   25,   25,   25,   25,},
 +{    3,    3,    4,   15,   15,   29,   57,   57,   57,  113,  113,  113,  113,  113,  113,  113,},
 +{    3,    4,    4,    5,   31,   31,   61,  121,  241,  241,  241,  241,  481,  481,  481,  481,},
 +{    3,    4,    5,    5,    6,   63,   63,  125,  249,  497,  993,  993,  993,  993,  993, 1985,},
 +{    3,    5,    6,    6,    6,    7,  127,  127,  253,  505, 1009, 2017, 4033, 4033, 4033, 4033,},
 +{    3,    5,    6,    7,    7,    7,    8,  255,  255,  509, 1017, 2033, 4065, 8129,16257,16257,},
 +{    3,    5,    6,    8,    8,    8,    8,    9,  511,  511, 1021, 2041, 4081, 8161,16321,32641,},
 +{    3,    5,    7,    8,    9,    9,    9,    9,   10, 1023, 1023, 2045, 4089, 8177,16353,32705,},
 +{    3,    5,    7,    8,   10,   10,   10,   10,   10,   11, 2047, 2047, 4093, 8185,16369,32737,},
 +{    3,    5,    7,    8,   10,   11,   11,   11,   11,   11,   12, 4095, 4095, 8189,16377,32753,},
 +{    3,    5,    7,    9,   10,   12,   12,   12,   12,   12,   12,   13, 8191, 8191,16381,32761,},
 +{    3,    5,    7,    9,   10,   12,   13,   13,   13,   13,   13,   13,   14,16383,16383,32765,},
 +{    3,    5,    7,    9,   10,   12,   14,   14,   14,   14,   14,   14,   14,   15,32767,32767,},
 +{    3,    5,    7,    9,   11,   12,   14,   15,   15,   15,   15,   15,   15,   15,   16,65535,},
 +};
 +
+ static av_always_inline void
+ yuv2yuvX16_c_template(const int16_t *lumFilter, const int16_t **lumSrc,
+                       int lumFilterSize, const int16_t *chrFilter,
+                       const int16_t **chrUSrc, const int16_t **chrVSrc,
+                       int chrFilterSize, const int16_t **alpSrc,
+                       uint16_t *dest, uint16_t *uDest, uint16_t *vDest,
+                       uint16_t *aDest, int dstW, int chrDstW,
+                       int big_endian, int output_bits)
  {
      //FIXME Optimize (just quickly written not optimized..)
      int i;
@@@ -387,40 -282,42 +377,40 @@@ yuv2NBPS(10, LE, 0)
  yuv2NBPS(16, BE, 1);
  yuv2NBPS(16, LE, 0);
  
- static inline void yuv2yuvX16inC(const int16_t *lumFilter, const int16_t **lumSrc, int lumFilterSize,
-                                  const int16_t *chrFilter, const int16_t **chrUSrc, const int16_t **chrVSrc, int chrFilterSize,
-                                  const int16_t **alpSrc, uint16_t *dest, uint16_t *uDest, uint16_t *vDest, uint16_t *aDest, int dstW, int chrDstW,
-                                  enum PixelFormat dstFormat)
+ static inline void yuv2yuvX16_c(const int16_t *lumFilter, const int16_t **lumSrc, int lumFilterSize,
+                                 const int16_t *chrFilter, const int16_t **chrUSrc, const int16_t **chrVSrc, int chrFilterSize,
+                                 const int16_t **alpSrc, uint16_t *dest, uint16_t *uDest, uint16_t *vDest, uint16_t *aDest, int dstW, int chrDstW,
+                                 enum PixelFormat dstFormat)
  {
 -#define conv16(bits) \
 -    if (isBE(dstFormat)) { \
 -        yuv2yuvX ## bits ## BE_c(lumFilter, lumSrc, lumFilterSize, \
 -                               chrFilter, chrUSrc, chrVSrc, chrFilterSize, \
 -                               alpSrc, \
 -                               dest, uDest, vDest, aDest, \
 -                               dstW, chrDstW); \
 -    } else { \
 -        yuv2yuvX ## bits ## LE_c(lumFilter, lumSrc, lumFilterSize, \
 -                               chrFilter, chrUSrc, chrVSrc, chrFilterSize, \
 -                               alpSrc, \
 -                               dest, uDest, vDest, aDest, \
 -                               dstW, chrDstW); \
 -    }
 -    if (is16BPS(dstFormat)) {
 -        conv16(16);
 -    } else if (av_pix_fmt_descriptors[dstFormat].comp[0].depth_minus1 == 8) {
 -        conv16(9);
 +    if (isNBPS(dstFormat)) {
 +        const int depth = av_pix_fmt_descriptors[dstFormat].comp[0].depth_minus1+1;
-         yuv2yuvX16inC_template(lumFilter, lumSrc, lumFilterSize,
++        yuv2yuvX16_c_template(lumFilter, lumSrc, lumFilterSize,
 +                              chrFilter, chrUSrc, chrVSrc, chrFilterSize,
 +                              alpSrc,
 +                              dest, uDest, vDest, aDest,
 +                              dstW, chrDstW, isBE(dstFormat), depth);
      } else {
 -        conv16(10);
 +        if (isBE(dstFormat)) {
-             yuv2yuvX16inC_template(lumFilter, lumSrc, lumFilterSize,
++            yuv2yuvX16_c_template(lumFilter, lumSrc, lumFilterSize,
 +                                   chrFilter, chrUSrc, chrVSrc, chrFilterSize,
 +                                   alpSrc,
 +                                   dest, uDest, vDest, aDest,
 +                                   dstW, chrDstW, 1, 16);
 +        } else {
-             yuv2yuvX16inC_template(lumFilter, lumSrc, lumFilterSize,
++            yuv2yuvX16_c_template(lumFilter, lumSrc, lumFilterSize,
 +                                   chrFilter, chrUSrc, chrVSrc, chrFilterSize,
 +                                   alpSrc,
 +                                   dest, uDest, vDest, aDest,
 +                                   dstW, chrDstW, 0, 16);
 +        }
      }
 -#undef conv16
  }
  
- static inline void yuv2yuvXinC(const int16_t *lumFilter, const int16_t **lumSrc, int lumFilterSize,
 -static inline void yuv2yuvX_c(SwsContext *c, const int16_t *lumFilter,
 -                              const int16_t **lumSrc, int lumFilterSize,
 -                              const int16_t *chrFilter, const int16_t **chrUSrc,
 -                              const int16_t **chrVSrc,
 -                              int chrFilterSize, const int16_t **alpSrc,
 -                              uint8_t *dest, uint8_t *uDest, uint8_t *vDest,
 -                              uint8_t *aDest, int dstW, int chrDstW)
++static void yuv2yuvX_c(SwsContext *c, const int16_t *lumFilter, const int16_t **lumSrc, int lumFilterSize,
 +                               const int16_t *chrFilter, const int16_t **chrUSrc,
 +                               const int16_t **chrVSrc, int chrFilterSize,
 +                               const int16_t **alpSrc, uint8_t *dest, uint8_t *uDest, uint8_t *vDest, uint8_t *aDest, int dstW, int chrDstW,
 +                               const uint8_t *lumDither, const uint8_t *chrDither)
  {
      //FIXME Optimize (just quickly written not optimized..)
      int i;
  
  }
  
- static inline void yuv2nv12XinC(const int16_t *lumFilter, const int16_t **lumSrc, int lumFilterSize,
-                                 const int16_t *chrFilter, const int16_t **chrUSrc,
-                                 const int16_t **chrVSrc, int chrFilterSize,
-                                 uint8_t *dest, uint8_t *uDest, int dstW, int chrDstW, int dstFormat,
-                                 const uint8_t *lumDither, const uint8_t *chrDither)
 -static inline void yuv2nv12X_c(SwsContext *c, const int16_t *lumFilter,
 -                               const int16_t **lumSrc, int lumFilterSize,
++static inline void yuv2nv12X_c(SwsContext *c, const int16_t *lumFilter, const int16_t **lumSrc, int lumFilterSize,
+                                const int16_t *chrFilter, const int16_t **chrUSrc,
 -                               const int16_t **chrVSrc,
 -                               int chrFilterSize, uint8_t *dest, uint8_t *uDest,
 -                               int dstW, int chrDstW, enum PixelFormat dstFormat)
++                               const int16_t **chrVSrc, int chrFilterSize,
++                               uint8_t *dest, uint8_t *uDest, int dstW, int chrDstW, int dstFormat,
++                               const uint8_t *lumDither, const uint8_t *chrDither)
  {
      //FIXME Optimize (just quickly written not optimized..)
      int i;
@@@ -1078,58 -976,97 +1068,58 @@@ static void fillPlane(uint8_t* plane, i
      }
  }
  
 -static void rgb48ToY_c(uint8_t *dst, const uint8_t *src, int width,
 -                       uint32_t *unused)
 -{
 -    int i;
 -    for (i = 0; i < width; i++) {
 -        int r = src[i*6+0];
 -        int g = src[i*6+2];
 -        int b = src[i*6+4];
 -
 -        dst[i] = (RY*r + GY*g + BY*b + (33<<(RGB2YUV_SHIFT-1))) >> RGB2YUV_SHIFT;
 -    }
 -}
 -
 -static void rgb48ToUV_c(uint8_t *dstU, uint8_t *dstV,
 -                        const uint8_t *src1, const uint8_t *src2,
 -                        int width, uint32_t *unused)
 -{
 -    int i;
 -    assert(src1==src2);
 -    for (i = 0; i < width; i++) {
 -        int r = src1[6*i + 0];
 -        int g = src1[6*i + 2];
 -        int b = src1[6*i + 4];
 -
 -        dstU[i] = (RU*r + GU*g + BU*b + (257<<(RGB2YUV_SHIFT-1))) >> RGB2YUV_SHIFT;
 -        dstV[i] = (RV*r + GV*g + BV*b + (257<<(RGB2YUV_SHIFT-1))) >> RGB2YUV_SHIFT;
 -    }
 -}
 -
 -static void rgb48ToUV_half_c(uint8_t *dstU, uint8_t *dstV,
 -                             const uint8_t *src1, const uint8_t *src2,
 -                             int width, uint32_t *unused)
 -{
 -    int i;
 -    assert(src1==src2);
 -    for (i = 0; i < width; i++) {
 -        int r= src1[12*i + 0] + src1[12*i + 6];
 -        int g= src1[12*i + 2] + src1[12*i + 8];
 -        int b= src1[12*i + 4] + src1[12*i + 10];
 -
 -        dstU[i]= (RU*r + GU*g + BU*b + (257<<RGB2YUV_SHIFT)) >> (RGB2YUV_SHIFT+1);
 -        dstV[i]= (RV*r + GV*g + BV*b + (257<<RGB2YUV_SHIFT)) >> (RGB2YUV_SHIFT+1);
 -    }
 -}
 -
 -static void bgr48ToY_c(uint8_t *dst, const uint8_t *src, int width,
 -                       uint32_t *unused)
 -{
 -    int i;
 -    for (i = 0; i < width; i++) {
 -        int b = src[i*6+0];
 -        int g = src[i*6+2];
 -        int r = src[i*6+4];
 -
 -        dst[i] = (RY*r + GY*g + BY*b + (33<<(RGB2YUV_SHIFT-1))) >> RGB2YUV_SHIFT;
 -    }
 +#define RGB48(name, R, B, READ)\
- static inline void name ## ToY(int16_t *dst, const uint16_t *src, int width, uint32_t *unused)\
++static inline void name ## ToY_c(int16_t *dst, const uint16_t *src, int width, uint32_t *unused)\
 +{\
 +    int i;\
 +    for (i = 0; i < width; i++) {\
 +        int r = READ(&src[i*3+R]);\
 +        int g = READ(&src[i*3+1]);\
 +        int b = READ(&src[i*3+B]);\
 +\
 +        dst[i] = (RY*r + GY*g + BY*b + (32<<(RGB2YUV_SHIFT-1+8)) + (1<<(RGB2YUV_SHIFT-7+8))) >> (RGB2YUV_SHIFT-6+8);\
 +    }\
 +}\
 +\
- static inline void name ## ToUV(int16_t *dstU, int16_t *dstV,\
++static inline void name ## ToUV_c(int16_t *dstU, int16_t *dstV,\
 +                             const uint16_t *src1, const uint16_t *src2,\
 +                             int width, uint32_t *unused)\
 +{\
 +    int i;\
 +    assert(src1==src2);\
 +    for (i = 0; i < width; i++) {\
 +        int r = READ(&src1[3*i + R]);\
 +        int g = READ(&src1[3*i + 1]);\
 +        int b = READ(&src1[3*i + B]);\
 +\
 +        dstU[i] = (RU*r + GU*g + BU*b + (256<<(RGB2YUV_SHIFT-1+8)) + (1<<(RGB2YUV_SHIFT-7+8))) >> (RGB2YUV_SHIFT-6+8);\
 +        dstV[i] = (RV*r + GV*g + BV*b + (256<<(RGB2YUV_SHIFT-1+8)) + (1<<(RGB2YUV_SHIFT-7+8))) >> (RGB2YUV_SHIFT-6+8);\
 +    }\
 +}\
 +\
- static inline void name ## ToUV_half(int16_t *dstU, int16_t *dstV,\
++static inline void name ## ToUV_half_c(int16_t *dstU, int16_t *dstV,\
 +                                  const uint16_t *src1, const uint16_t *src2,\
 +                                  int width, uint32_t *unused)\
 +{\
 +    int i;\
 +    assert(src1==src2);\
 +    for (i = 0; i < width; i++) {\
 +        int r= READ(&src1[6*i + R]) + READ(&src1[6*i + 3+R]);\
 +        int g= READ(&src1[6*i + 1]) + READ(&src1[6*i + 4]);\
 +        int b= READ(&src1[6*i + B]) + READ(&src1[6*i + 3+B]);\
 +\
 +        dstU[i]= (RU*r + GU*g + BU*b + (256U<<(RGB2YUV_SHIFT+8)) + (1<<(RGB2YUV_SHIFT-6+8))) >> (RGB2YUV_SHIFT-5+8);\
 +        dstV[i]= (RV*r + GV*g + BV*b + (256U<<(RGB2YUV_SHIFT+8)) + (1<<(RGB2YUV_SHIFT-6+8))) >> (RGB2YUV_SHIFT-5+8);\
 +    }\
  }
  
 -static void bgr48ToUV_c(uint8_t *dstU, uint8_t *dstV,
 -                        const uint8_t *src1, const uint8_t *src2,
 -                        int width, uint32_t *unused)
 -{
 -    int i;
 -    for (i = 0; i < width; i++) {
 -        int b = src1[6*i + 0];
 -        int g = src1[6*i + 2];
 -        int r = src1[6*i + 4];
 -
 -        dstU[i] = (RU*r + GU*g + BU*b + (257<<(RGB2YUV_SHIFT-1))) >> RGB2YUV_SHIFT;
 -        dstV[i] = (RV*r + GV*g + BV*b + (257<<(RGB2YUV_SHIFT-1))) >> RGB2YUV_SHIFT;
 -    }
 -}
 -
 -static void bgr48ToUV_half_c(uint8_t *dstU, uint8_t *dstV,
 -                             const uint8_t *src1, const uint8_t *src2,
 -                             int width, uint32_t *unused)
 -{
 -    int i;
 -    for (i = 0; i < width; i++) {
 -        int b= src1[12*i + 0] + src1[12*i + 6];
 -        int g= src1[12*i + 2] + src1[12*i + 8];
 -        int r= src1[12*i + 4] + src1[12*i + 10];
 -
 -        dstU[i]= (RU*r + GU*g + BU*b + (257<<RGB2YUV_SHIFT)) >> (RGB2YUV_SHIFT+1);
 -        dstV[i]= (RV*r + GV*g + BV*b + (257<<RGB2YUV_SHIFT)) >> (RGB2YUV_SHIFT+1);
 -    }
 -}
 +RGB48(rgb48LE, 0, 2, AV_RL16)
 +RGB48(rgb48BE, 0, 2, AV_RB16)
 +RGB48(bgr48LE, 2, 0, AV_RL16)
 +RGB48(bgr48BE, 2, 0, AV_RB16)
  
  #define BGR2Y(type, name, shr, shg, shb, maskr, maskg, maskb, RY, GY, BY, S)\
- static inline void name(int16_t *dst, const uint8_t *src, int width, uint32_t *unused)\
 -static void name ## _c(uint8_t *dst, const uint8_t *src, \
 -                       int width, uint32_t *unused)\
++static void name ## _c(int16_t *dst, const uint8_t *src, int width, uint32_t *unused)\
  {\
      int i;\
      for (i=0; i<width; i++) {\
@@@ -1150,7 -1087,7 +1140,7 @@@ BGR2Y(uint16_t, bgr15ToY, 0, 0, 0, 0x00
  BGR2Y(uint16_t, rgb16ToY, 0, 0, 0, 0xF800, 0x07E0, 0x001F, RY    , GY<<5, BY<<11, RGB2YUV_SHIFT+8)
  BGR2Y(uint16_t, rgb15ToY, 0, 0, 0, 0x7C00, 0x03E0, 0x001F, RY    , GY<<5, BY<<10, RGB2YUV_SHIFT+7)
  
- static inline void abgrToA(int16_t *dst, const uint8_t *src, int width, uint32_t *unused)
 -static void abgrToA_c(uint8_t *dst, const uint8_t *src, int width, uint32_t *unused)
++static void abgrToA_c(int16_t *dst, const uint8_t *src, int width, uint32_t *unused)
  {
      int i;
      for (i=0; i<width; i++) {
  }
  
  #define BGR2UV(type, name, shr, shg, shb, shp, maskr, maskg, maskb, RU, GU, BU, RV, GV, BV, S) \
- static inline void name(int16_t *dstU, int16_t *dstV, const uint8_t *src, const uint8_t *dummy, int width, uint32_t *unused)\
 -static void name ## _c(uint8_t *dstU, uint8_t *dstV, \
 -                       const uint8_t *src, const uint8_t *dummy, \
 -                       int width, uint32_t *unused)\
++static  void name ## _c(int16_t *dstU, int16_t *dstV, const uint8_t *src, const uint8_t *dummy, int width, uint32_t *unused)\
  {\
      int i;\
      for (i=0; i<width; i++) {\
          int g= ((((const type*)src)[i]>>shp)&maskg)>>shg;\
          int r= ((((const type*)src)[i]>>shp)&maskr)>>shr;\
  \
 -        dstU[i]= ((RU)*r + (GU)*g + (BU)*b + (257<<((S)-1)))>>(S);\
 -        dstV[i]= ((RV)*r + (GV)*g + (BV)*b + (257<<((S)-1)))>>(S);\
 +        dstU[i]= ((RU)*r + (GU)*g + (BU)*b + (256<<((S)-1)) + (1<<(S-7)))>>((S)-6);\
 +        dstV[i]= ((RV)*r + (GV)*g + (BV)*b + (256<<((S)-1)) + (1<<(S-7)))>>((S)-6);\
      }\
  }\
- static inline void name ## _half(int16_t *dstU, int16_t *dstV, const uint8_t *src, const uint8_t *dummy, int width, uint32_t *unused)\
 -static void name ## _half_c(uint8_t *dstU, uint8_t *dstV, \
 -                            const uint8_t *src, const uint8_t *dummy, \
 -                            int width, uint32_t *unused)\
++static void name ## _half_c(int16_t *dstU, int16_t *dstV, const uint8_t *src, const uint8_t *dummy, int width, uint32_t *unused)\
  {\
      int i;\
      for (i=0; i<width; i++) {\
@@@ -1198,17 -1139,7 +1188,17 @@@ BGR2UV(uint16_t, bgr15ToUV, 0, 0, 0, 0
  BGR2UV(uint16_t, rgb16ToUV, 0, 0, 0, 0,   0xF800, 0x07E0,   0x001F, RU    , GU<<5, BU<<11, RV    , GV<<5, BV<<11, RGB2YUV_SHIFT+8)
  BGR2UV(uint16_t, rgb15ToUV, 0, 0, 0, 0,   0x7C00, 0x03E0,   0x001F, RU    , GU<<5, BU<<10, RV    , GV<<5, BV<<10, RGB2YUV_SHIFT+7)
  
- static inline void palToA(int16_t *dst, const uint8_t *src, int width, uint32_t *pal)
 -static void palToY_c(uint8_t *dst, const uint8_t *src, int width, uint32_t *pal)
++static void palToA_c(int16_t *dst, const uint8_t *src, int width, uint32_t *pal)
 +{
 +    int i;
 +    for (i=0; i<width; i++) {
 +        int d= src[i];
 +
 +        dst[i]= (pal[d] >> 24)<<6;
 +    }
 +}
 +
- static inline void palToY(int16_t *dst, const uint8_t *src, long width, uint32_t *pal)
++static void palToY_c(int16_t *dst, const uint8_t *src, long width, uint32_t *pal)
  {
      int i;
      for (i=0; i<width; i++) {
      }
  }
  
- static inline void palToUV(uint16_t *dstU, int16_t *dstV,
 -static void palToUV_c(uint8_t *dstU, uint8_t *dstV,
 -                      const uint8_t *src1, const uint8_t *src2,
 -                      int width, uint32_t *pal)
++static void palToUV_c(uint16_t *dstU, int16_t *dstV,
 +                           const uint8_t *src1, const uint8_t *src2,
 +                           int width, uint32_t *pal)
  {
      int i;
      assert(src1 == src2);
      }
  }
  
- static inline void monowhite2Y(int16_t *dst, const uint8_t *src, int width, uint32_t *unused)
 -static void monowhite2Y_c(uint8_t *dst, const uint8_t *src,
 -                          int width, uint32_t *unused)
++static void monowhite2Y_c(int16_t *dst, const uint8_t *src, int width, uint32_t *unused)
  {
      int i, j;
      for (i=0; i<width/8; i++) {
      }
  }
  
- static inline void monoblack2Y(int16_t *dst, const uint8_t *src, int width, uint32_t *unused)
 -static void monoblack2Y_c(uint8_t *dst, const uint8_t *src,
 -                          int width, uint32_t *unused)
++static void monoblack2Y_c(int16_t *dst, const uint8_t *src, int width, uint32_t *unused)
  {
      int i, j;
      for (i=0; i<width/8; i++) {
      }
  }
  
- //Note: we have C, MMX, MMX2, 3DNOW versions, there is no 3DNOW+MMX2 one
- //Plain C versions
+ static void yuv2yuv1_c(SwsContext *c, const int16_t *lumSrc,
 -                       const int16_t *chrUSrc, const int16_t *chrVSrc,
 -                       const int16_t *alpSrc,
 -                       uint8_t *dest, uint8_t *uDest, uint8_t *vDest,
 -                       uint8_t *aDest, int dstW, int chrDstW)
++                              const int16_t *chrUSrc, const int16_t *chrVSrc,
++                              const int16_t *alpSrc,
++                              uint8_t *dest, uint8_t *uDest, uint8_t *vDest,
++                              uint8_t *aDest, int dstW, int chrDstW, const uint8_t *lumDither, const uint8_t *chrDither)
+ {
+     int i;
 +
- #define COMPILE_TEMPLATE_MMX2 0
- #define COMPILE_TEMPLATE_ALTIVEC 0
+     for (i=0; i<dstW; i++) {
 -        int val= (lumSrc[i]+64)>>7;
++        int val= (lumSrc[i]+lumDither[i&7])>>7;
+         dest[i]= av_clip_uint8(val);
+     }
  
- #include "swscale_template.c"
+     if (uDest)
+         for (i=0; i<chrDstW; i++) {
 -            int u=(chrUSrc[i]+64)>>7;
 -            int v=(chrVSrc[i]+64)>>7;
++            int u=(chrUSrc[i]+chrDither[i&7])>>7;
++            int v=(chrVSrc[i]+chrDither[(i+3)&7])>>7;
+             uDest[i]= av_clip_uint8(u);
+             vDest[i]= av_clip_uint8(v);
+         }
  
- #if HAVE_ALTIVEC
- #undef RENAME
- #undef COMPILE_TEMPLATE_ALTIVEC
- #define COMPILE_TEMPLATE_ALTIVEC 1
- #define RENAME(a) a ## _altivec
- #include "ppc/swscale_template.c"
- #endif
+     if (CONFIG_SWSCALE_ALPHA && aDest)
+         for (i=0; i<dstW; i++) {
 -            int val= (alpSrc[i]+64)>>7;
++            int val= (alpSrc[i]+lumDither[i&7])>>7;
+             aDest[i]= av_clip_uint8(val);
+         }
+ }
  
- //MMX versions
- #if HAVE_MMX
- #undef RENAME
- #undef COMPILE_TEMPLATE_MMX2
- #define COMPILE_TEMPLATE_MMX2 0
- #define RENAME(a) a ## _MMX
- #include "x86/swscale_template.c"
- #endif
+ /**
+  * vertical bilinear scale YV12 to RGB
+  */
+ static void yuv2packed2_c(SwsContext *c, const uint16_t *buf0,
+                           const uint16_t *buf1, const uint16_t *ubuf0,
+                           const uint16_t *ubuf1, const uint16_t *vbuf0,
+                           const uint16_t *vbuf1, const uint16_t *abuf0,
+                           const uint16_t *abuf1, uint8_t *dest, int dstW,
+                           int yalpha, int uvalpha, int y)
+ {
+     int  yalpha1=4095- yalpha;
+     int uvalpha1=4095-uvalpha;
+     int i;
  
- //MMX2 versions
- #if HAVE_MMX2
- #undef RENAME
- #undef COMPILE_TEMPLATE_MMX2
- #define COMPILE_TEMPLATE_MMX2 1
- #define RENAME(a) a ## _MMX2
- #include "x86/swscale_template.c"
- #endif
+     YSCALE_YUV_2_ANYRGB_C(YSCALE_YUV_2_RGB2_C, YSCALE_YUV_2_PACKED2_C(void,0), YSCALE_YUV_2_GRAY16_2_C, YSCALE_YUV_2_MONO2_C)
+ }
  
- SwsFunc ff_getSwsFunc(SwsContext *c)
+ /**
+  * YV12 to RGB without scaling or interpolating
+  */
+ static void yuv2packed1_c(SwsContext *c, const uint16_t *buf0,
+                           const uint16_t *ubuf0, const uint16_t *ubuf1,
+                           const uint16_t *vbuf0, const uint16_t *vbuf1,
+                           const uint16_t *abuf0, uint8_t *dest, int dstW,
+                           int uvalpha, enum PixelFormat dstFormat,
+                           int flags, int y)
  {
-     int cpu_flags = av_get_cpu_flags();
+     const int yalpha1=0;
+     int i;
  
-     sws_init_swScale_c(c);
+     const uint16_t *buf1= buf0; //FIXME needed for RGB1/BGR1
+     const int yalpha= 4096; //FIXME ...
  
- #if HAVE_MMX
-     if (cpu_flags & AV_CPU_FLAG_MMX)
-         sws_init_swScale_MMX(c);
- #endif
- #if HAVE_MMX2
-     if (cpu_flags & AV_CPU_FLAG_MMX2)
-         sws_init_swScale_MMX2(c);
- #endif
- #if HAVE_ALTIVEC
-     if (cpu_flags & AV_CPU_FLAG_ALTIVEC)
-         sws_init_swScale_altivec(c);
- #endif
+     if (uvalpha < 2048) {
+         YSCALE_YUV_2_ANYRGB_C(YSCALE_YUV_2_RGB1_C, YSCALE_YUV_2_PACKED1_C(void,0), YSCALE_YUV_2_GRAY16_1_C, YSCALE_YUV_2_MONO2_C)
+     } else {
+         YSCALE_YUV_2_ANYRGB_C(YSCALE_YUV_2_RGB1B_C, YSCALE_YUV_2_PACKED1B_C(void,0), YSCALE_YUV_2_GRAY16_1_C, YSCALE_YUV_2_MONO2_C)
+     }
+ }
+ //FIXME yuy2* can read up to 7 samples too much
  
-     return swScale_c;
+ static void yuy2ToY_c(uint8_t *dst, const uint8_t *src, int width,
+                       uint32_t *unused)
+ {
+     int i;
+     for (i=0; i<width; i++)
+         dst[i]= src[2*i];
  }
  
- static void copyPlane(const uint8_t *src, int srcStride,
-                       int srcSliceY, int srcSliceH, int width,
-                       uint8_t *dst, int dstStride)
+ static void yuy2ToUV_c(uint8_t *dstU, uint8_t *dstV, const uint8_t *src1,
+                        const uint8_t *src2, int width, uint32_t *unused)
  {
-     dst += dstStride * srcSliceY;
-     if (dstStride == srcStride && srcStride > 0) {
-         memcpy(dst, src, srcSliceH * dstStride);
-     } else {
-         int i;
-         for (i=0; i<srcSliceH; i++) {
-             memcpy(dst, src, width);
-             src += srcStride;
-             dst += dstStride;
-         }
+     int i;
+     for (i=0; i<width; i++) {
+         dstU[i]= src1[4*i + 1];
+         dstV[i]= src1[4*i + 3];
      }
+     assert(src1 == src2);
  }
  
- static int planarToNv12Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
-                                int srcSliceH, uint8_t* dstParam[], int dstStride[])
+ static void LEToUV_c(uint8_t *dstU, uint8_t *dstV, const uint8_t *src1,
+                      const uint8_t *src2, int width, uint32_t *unused)
  {
-     uint8_t *dst = dstParam[1] + dstStride[1]*srcSliceY/2;
-     copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW,
-               dstParam[0], dstStride[0]);
-     if (c->dstFormat == PIX_FMT_NV12)
-         interleaveBytes(src[1], src[2], dst, c->srcW/2, srcSliceH/2, srcStride[1], srcStride[2], dstStride[0]);
-     else
-         interleaveBytes(src[2], src[1], dst, c->srcW/2, srcSliceH/2, srcStride[2], srcStride[1], dstStride[0]);
-     return srcSliceH;
+     int i;
+     for (i=0; i<width; i++) {
+         dstU[i]= src1[2*i + 1];
+         dstV[i]= src2[2*i + 1];
+     }
  }
  
- static int planarToYuy2Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
-                                int srcSliceH, uint8_t* dstParam[], int dstStride[])
+ /* This is almost identical to the previous, end exists only because
+  * yuy2ToY/UV)(dst, src+1, ...) would have 100% unaligned accesses. */
+ static void uyvyToY_c(uint8_t *dst, const uint8_t *src, int width,
+                       uint32_t *unused)
  {
-     uint8_t *dst=dstParam[0] + dstStride[0]*srcSliceY;
-     yv12toyuy2(src[0], src[1], src[2], dst, c->srcW, srcSliceH, srcStride[0], srcStride[1], dstStride[0]);
-     return srcSliceH;
+     int i;
+     for (i=0; i<width; i++)
+         dst[i]= src[2*i+1];
  }
  
- static int planarToUyvyWrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
-                                int srcSliceH, uint8_t* dstParam[], int dstStride[])
+ static void uyvyToUV_c(uint8_t *dstU, uint8_t *dstV, const uint8_t *src1,
+                        const uint8_t *src2, int width, uint32_t *unused)
  {
-     uint8_t *dst=dstParam[0] + dstStride[0]*srcSliceY;
-     yv12touyvy(src[0], src[1], src[2], dst, c->srcW, srcSliceH, srcStride[0], srcStride[1], dstStride[0]);
-     return srcSliceH;
+     int i;
+     for (i=0; i<width; i++) {
+         dstU[i]= src1[4*i + 0];
+         dstV[i]= src1[4*i + 2];
+     }
+     assert(src1 == src2);
  }
  
- static int yuv422pToYuy2Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
-                                 int srcSliceH, uint8_t* dstParam[], int dstStride[])
+ static void BEToUV_c(uint8_t *dstU, uint8_t *dstV, const uint8_t *src1,
+                      const uint8_t *src2, int width, uint32_t *unused)
  {
-     uint8_t *dst=dstParam[0] + dstStride[0]*srcSliceY;
-     yuv422ptoyuy2(src[0],src[1],src[2],dst,c->srcW,srcSliceH,srcStride[0],srcStride[1],dstStride[0]);
-     return srcSliceH;
+     int i;
+     for (i=0; i<width; i++) {
+         dstU[i]= src1[2*i];
+         dstV[i]= src2[2*i];
+     }
  }
  
- static int yuv422pToUyvyWrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
-                                 int srcSliceH, uint8_t* dstParam[], int dstStride[])
+ static av_always_inline void nvXXtoUV_c(uint8_t *dst1, uint8_t *dst2,
+                                         const uint8_t *src, int width)
  {
-     uint8_t *dst=dstParam[0] + dstStride[0]*srcSliceY;
-     yuv422ptouyvy(src[0],src[1],src[2],dst,c->srcW,srcSliceH,srcStride[0],srcStride[1],dstStride[0]);
-     return srcSliceH;
+     int i;
+     for (i = 0; i < width; i++) {
+         dst1[i] = src[2*i+0];
+         dst2[i] = src[2*i+1];
+     }
  }
  
- static int yuyvToYuv420Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
-                                int srcSliceH, uint8_t* dstParam[], int dstStride[])
 -static void nv12ToUV_c(uint8_t *dstU, uint8_t *dstV,
 -                       const uint8_t *src1, const uint8_t *src2,
 -                       int width, uint32_t *unused)
 -{
 -    nvXXtoUV_c(dstU, dstV, src1, width);
 -}
 -
 -static void nv21ToUV_c(uint8_t *dstU, uint8_t *dstV,
 -                       const uint8_t *src1, const uint8_t *src2,
 -                       int width, uint32_t *unused)
 -{
 -    nvXXtoUV_c(dstV, dstU, src1, width);
 -}
 -
+ // FIXME Maybe dither instead.
++#ifndef YUV_NBPS
+ #define YUV_NBPS(depth, endianness, rfunc) \
+ static void endianness ## depth ## ToUV_c(uint8_t *dstU, uint8_t *dstV, \
 -                                          const uint8_t *_srcU, const uint8_t *_srcV, \
++                                          const uint16_t *srcU, const uint16_t *srcV, \
+                                           int width, uint32_t *unused) \
+ { \
+     int i; \
 -    const uint16_t *srcU = (const uint16_t*)_srcU; \
 -    const uint16_t *srcV = (const uint16_t*)_srcV; \
+     for (i = 0; i < width; i++) { \
+         dstU[i] = rfunc(&srcU[i])>>(depth-8); \
+         dstV[i] = rfunc(&srcV[i])>>(depth-8); \
+     } \
+ } \
+ \
 -static void endianness ## depth ## ToY_c(uint8_t *dstY, const uint8_t *_srcY, \
 -                                         int width, uint32_t *unused) \
++static void endianness ## depth ## ToY_c(uint8_t *dstY, const uint16_t *srcY, int width, uint32_t *unused) \
+ { \
+     int i; \
 -    const uint16_t *srcY = (const uint16_t*)_srcY; \
+     for (i = 0; i < width; i++) \
+         dstY[i] = rfunc(&srcY[i])>>(depth-8); \
+ } \
+ YUV_NBPS( 9, LE, AV_RL16)
+ YUV_NBPS( 9, BE, AV_RB16)
+ YUV_NBPS(10, LE, AV_RL16)
+ YUV_NBPS(10, BE, AV_RB16)
++#endif // YUV_NBPS
++
++static inline void nv12ToUV_c(uint8_t *dstU, uint8_t *dstV,
++                              const uint8_t *src1, const uint8_t *src2,
++                              int width, uint32_t *unused)
 +{
-     uint8_t *ydst=dstParam[0] + dstStride[0]*srcSliceY;
-     uint8_t *udst=dstParam[1] + dstStride[1]*srcSliceY/2;
-     uint8_t *vdst=dstParam[2] + dstStride[2]*srcSliceY/2;
-     yuyvtoyuv420(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0], dstStride[1], srcStride[0]);
-     if (dstParam[3])
-         fillPlane(dstParam[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255);
-     return srcSliceH;
++    nvXXtoUV_c(dstU, dstV, src1, width);
 +}
 +
- static int yuyvToYuv422Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
-                                int srcSliceH, uint8_t* dstParam[], int dstStride[])
++static inline void nv21ToUV_c(uint8_t *dstU, uint8_t *dstV,
++                              const uint8_t *src1, const uint8_t *src2,
++                              int width, uint32_t *unused)
 +{
-     uint8_t *ydst=dstParam[0] + dstStride[0]*srcSliceY;
-     uint8_t *udst=dstParam[1] + dstStride[1]*srcSliceY;
-     uint8_t *vdst=dstParam[2] + dstStride[2]*srcSliceY;
-     yuyvtoyuv422(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0], dstStride[1], srcStride[0]);
-     return srcSliceH;
++    nvXXtoUV_c(dstV, dstU, src1, width);
 +}
  
- static int uyvyToYuv420Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
-                                int srcSliceH, uint8_t* dstParam[], int dstStride[])
 -static void bgr24ToY_c(uint8_t *dst, const uint8_t *src,
++static void bgr24ToY_c(int16_t *dst, const uint8_t *src,
+                        int width, uint32_t *unused)
  {
-     uint8_t *ydst=dstParam[0] + dstStride[0]*srcSliceY;
-     uint8_t *udst=dstParam[1] + dstStride[1]*srcSliceY/2;
-     uint8_t *vdst=dstParam[2] + dstStride[2]*srcSliceY/2;
+     int i;
+     for (i=0; i<width; i++) {
+         int b= src[i*3+0];
+         int g= src[i*3+1];
+         int r= src[i*3+2];
  
-     uyvytoyuv420(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0], dstStride[1], srcStride[0]);
 -        dst[i]= ((RY*r + GY*g + BY*b + (33<<(RGB2YUV_SHIFT-1)))>>RGB2YUV_SHIFT);
++        dst[i]= ((RY*r + GY*g + BY*b + (32<<(RGB2YUV_SHIFT-1)) + (1<<(RGB2YUV_SHIFT-7)))>>(RGB2YUV_SHIFT-6));
+     }
+ }
  
-     if (dstParam[3])
-         fillPlane(dstParam[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255);
 -static void bgr24ToUV_c(uint8_t *dstU, uint8_t *dstV, const uint8_t *src1,
++static void bgr24ToUV_c(int16_t *dstU, int16_t *dstV, const uint8_t *src1,
+                         const uint8_t *src2, int width, uint32_t *unused)
+ {
+     int i;
+     for (i=0; i<width; i++) {
+         int b= src1[3*i + 0];
+         int g= src1[3*i + 1];
+         int r= src1[3*i + 2];
  
-     return srcSliceH;
 -        dstU[i]= (RU*r + GU*g + BU*b + (257<<(RGB2YUV_SHIFT-1)))>>RGB2YUV_SHIFT;
 -        dstV[i]= (RV*r + GV*g + BV*b + (257<<(RGB2YUV_SHIFT-1)))>>RGB2YUV_SHIFT;
++        dstU[i]= (RU*r + GU*g + BU*b + (256<<(RGB2YUV_SHIFT-1)) + (1<<(RGB2YUV_SHIFT-7)))>>(RGB2YUV_SHIFT-6);
++        dstV[i]= (RV*r + GV*g + BV*b + (256<<(RGB2YUV_SHIFT-1)) + (1<<(RGB2YUV_SHIFT-7)))>>(RGB2YUV_SHIFT-6);
+     }
+     assert(src1 == src2);
  }
  
- static int uyvyToYuv422Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
-                                int srcSliceH, uint8_t* dstParam[], int dstStride[])
 -static void bgr24ToUV_half_c(uint8_t *dstU, uint8_t *dstV, const uint8_t *src1,
++static void bgr24ToUV_half_c(int16_t *dstU, int16_t *dstV, const uint8_t *src1,
+                              const uint8_t *src2, int width, uint32_t *unused)
  {
-     uint8_t *ydst=dstParam[0] + dstStride[0]*srcSliceY;
-     uint8_t *udst=dstParam[1] + dstStride[1]*srcSliceY;
-     uint8_t *vdst=dstParam[2] + dstStride[2]*srcSliceY;
-     uyvytoyuv422(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0], dstStride[1], srcStride[0]);
+     int i;
+     for (i=0; i<width; i++) {
+         int b= src1[6*i + 0] + src1[6*i + 3];
+         int g= src1[6*i + 1] + src1[6*i + 4];
+         int r= src1[6*i + 2] + src1[6*i + 5];
  
-     return srcSliceH;
 -        dstU[i]= (RU*r + GU*g + BU*b + (257<<RGB2YUV_SHIFT))>>(RGB2YUV_SHIFT+1);
 -        dstV[i]= (RV*r + GV*g + BV*b + (257<<RGB2YUV_SHIFT))>>(RGB2YUV_SHIFT+1);
++        dstU[i]= (RU*r + GU*g + BU*b + (256<<RGB2YUV_SHIFT) + (1<<(RGB2YUV_SHIFT-6)))>>(RGB2YUV_SHIFT-5);
++        dstV[i]= (RV*r + GV*g + BV*b + (256<<RGB2YUV_SHIFT) + (1<<(RGB2YUV_SHIFT-6)))>>(RGB2YUV_SHIFT-5);
+     }
+     assert(src1 == src2);
  }
  
- static void gray8aToPacked32(const uint8_t *src, uint8_t *dst, int num_pixels, const uint8_t *palette)
 -static void rgb24ToY_c(uint8_t *dst, const uint8_t *src, int width,
++static void rgb24ToY_c(int16_t *dst, const uint8_t *src, int width,
+                        uint32_t *unused)
  {
      int i;
-     for (i=0; i<num_pixels; i++)
-         ((uint32_t *) dst)[i] = ((const uint32_t *)palette)[src[i<<1]] | (src[(i<<1)+1] << 24);
+     for (i=0; i<width; i++) {
+         int r= src[i*3+0];
+         int g= src[i*3+1];
+         int b= src[i*3+2];
 -        dst[i]= ((RY*r + GY*g + BY*b + (33<<(RGB2YUV_SHIFT-1)))>>RGB2YUV_SHIFT);
++        dst[i]= ((RY*r + GY*g + BY*b + (32<<(RGB2YUV_SHIFT-1)) + (1<<(RGB2YUV_SHIFT-7)))>>(RGB2YUV_SHIFT-6));
+     }
  }
  
- static void gray8aToPacked32_1(const uint8_t *src, uint8_t *dst, int num_pixels, const uint8_t *palette)
 -static void rgb24ToUV_c(uint8_t *dstU, uint8_t *dstV, const uint8_t *src1,
++static void rgb24ToUV_c(int16_t *dstU, int16_t *dstV, const uint8_t *src1,
+                         const uint8_t *src2, int width, uint32_t *unused)
  {
      int i;
+     assert(src1==src2);
+     for (i=0; i<width; i++) {
+         int r= src1[3*i + 0];
+         int g= src1[3*i + 1];
+         int b= src1[3*i + 2];
  
-     for (i=0; i<num_pixels; i++)
-         ((uint32_t *) dst)[i] = ((const uint32_t *)palette)[src[i<<1]] | src[(i<<1)+1];
 -        dstU[i]= (RU*r + GU*g + BU*b + (257<<(RGB2YUV_SHIFT-1)))>>RGB2YUV_SHIFT;
 -        dstV[i]= (RV*r + GV*g + BV*b + (257<<(RGB2YUV_SHIFT-1)))>>RGB2YUV_SHIFT;
++        dstU[i]= (RU*r + GU*g + BU*b + (256<<(RGB2YUV_SHIFT-1)) + (1<<(RGB2YUV_SHIFT-7)))>>(RGB2YUV_SHIFT-6);
++        dstV[i]= (RV*r + GV*g + BV*b + (256<<(RGB2YUV_SHIFT-1)) + (1<<(RGB2YUV_SHIFT-7)))>>(RGB2YUV_SHIFT-6);
+     }
  }
  
- static void gray8aToPacked24(const uint8_t *src, uint8_t *dst, int num_pixels, const uint8_t *palette)
 -static void rgb24ToUV_half_c(uint8_t *dstU, uint8_t *dstV, const uint8_t *src1,
 -                             const uint8_t *src2, int width, uint32_t *unused)
++static void rgb24ToUV_half_c(int16_t *dstU, int16_t *dstV, const uint8_t *src1,
++                                    const uint8_t *src2, int width, uint32_t *unused)
  {
      int i;
+     assert(src1==src2);
+     for (i=0; i<width; i++) {
+         int r= src1[6*i + 0] + src1[6*i + 3];
+         int g= src1[6*i + 1] + src1[6*i + 4];
+         int b= src1[6*i + 2] + src1[6*i + 5];
  
-     for (i=0; i<num_pixels; i++) {
-         //FIXME slow?
-         dst[0]= palette[src[i<<1]*4+0];
-         dst[1]= palette[src[i<<1]*4+1];
-         dst[2]= palette[src[i<<1]*4+2];
-         dst+= 3;
 -        dstU[i]= (RU*r + GU*g + BU*b + (257<<RGB2YUV_SHIFT))>>(RGB2YUV_SHIFT+1);
 -        dstV[i]= (RV*r + GV*g + BV*b + (257<<RGB2YUV_SHIFT))>>(RGB2YUV_SHIFT+1);
++        dstU[i]= (RU*r + GU*g + BU*b + (256<<RGB2YUV_SHIFT) + (1<<(RGB2YUV_SHIFT-6)))>>(RGB2YUV_SHIFT-5);
++        dstV[i]= (RV*r + GV*g + BV*b + (256<<RGB2YUV_SHIFT) + (1<<(RGB2YUV_SHIFT-6)))>>(RGB2YUV_SHIFT-5);
      }
  }
  
- static int palToRgbWrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
-                            int srcSliceH, uint8_t* dst[], int dstStride[])
+ // bilinear / bicubic scaling
+ static void hScale_c(int16_t *dst, int dstW, const uint8_t *src,
+                      int srcW, int xInc,
+                      const int16_t *filter, const int16_t *filterPos,
+                      int filterSize)
  {
-     const enum PixelFormat srcFormat= c->srcFormat;
-     const enum PixelFormat dstFormat= c->dstFormat;
-     void (*conv)(const uint8_t *src, uint8_t *dst, int num_pixels,
-                  const uint8_t *palette)=NULL;
      int i;
-     uint8_t *dstPtr= dst[0] + dstStride[0]*srcSliceY;
-     const uint8_t *srcPtr= src[0];
-     if (srcFormat == PIX_FMT_GRAY8A) {
-         switch (dstFormat) {
-         case PIX_FMT_RGB32  : conv = gray8aToPacked32; break;
-         case PIX_FMT_BGR32  : conv = gray8aToPacked32; break;
-         case PIX_FMT_BGR32_1: conv = gray8aToPacked32_1; break;
-         case PIX_FMT_RGB32_1: conv = gray8aToPacked32_1; break;
-         case PIX_FMT_RGB24  : conv = gray8aToPacked24; break;
-         case PIX_FMT_BGR24  : conv = gray8aToPacked24; break;
-         }
-     } else if (usePal(srcFormat)) {
-         switch (dstFormat) {
-         case PIX_FMT_RGB32  : conv = sws_convertPalette8ToPacked32; break;
-         case PIX_FMT_BGR32  : conv = sws_convertPalette8ToPacked32; break;
-         case PIX_FMT_BGR32_1: conv = sws_convertPalette8ToPacked32; break;
-         case PIX_FMT_RGB32_1: conv = sws_convertPalette8ToPacked32; break;
-         case PIX_FMT_RGB24  : conv = sws_convertPalette8ToPacked24; break;
-         case PIX_FMT_BGR24  : conv = sws_convertPalette8ToPacked24; break;
+     for (i=0; i<dstW; i++) {
+         int j;
+         int srcPos= filterPos[i];
+         int val=0;
+         for (j=0; j<filterSize; j++) {
+             val += ((int)src[srcPos + j])*filter[filterSize*i + j];
          }
+         //filter += hFilterSize;
+         dst[i] = FFMIN(val>>7, (1<<15)-1); // the cubic equation does overflow ...
+         //dst[i] = val>>7;
      }
+ }
  
-     if (!conv)
-         av_log(c, AV_LOG_ERROR, "internal error %s -> %s converter\n",
-                av_get_pix_fmt_name(srcFormat), av_get_pix_fmt_name(dstFormat));
-     else {
-         for (i=0; i<srcSliceH; i++) {
-             conv(srcPtr, dstPtr, c->srcW, (uint8_t *) c->pal_rgb);
-             srcPtr+= srcStride[0];
-             dstPtr+= dstStride[0];
++static inline void hScale16_c(int16_t *dst, int dstW, const uint16_t *src, int srcW, int xInc,
++                                    const int16_t *filter, const int16_t *filterPos, long filterSize, int shift)
++{
++    int i, j;
++
++    for (i=0; i<dstW; i++) {
++        int srcPos= filterPos[i];
++        int val=0;
++        for (j=0; j<filterSize; j++) {
++            val += ((int)src[srcPos + j])*filter[filterSize*i + j];
 +        }
++        dst[i] = FFMIN(val>>shift, (1<<15)-1); // the cubic equation does overflow ...
 +    }
-     return srcSliceH;
 +}
 +
- #define isRGBA32(x) (            \
-            (x) == PIX_FMT_ARGB   \
-         || (x) == PIX_FMT_RGBA   \
-         || (x) == PIX_FMT_BGRA   \
-         || (x) == PIX_FMT_ABGR   \
-         )
- /* {RGB,BGR}{15,16,24,32,32_1} -> {RGB,BGR}{15,16,24,32} */
- static int rgbToRgbWrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
-                            int srcSliceH, uint8_t* dst[], int dstStride[])
++static inline void hScale16X_c(int16_t *dst, int dstW, const uint16_t *src, int srcW, int xInc,
++                                    const int16_t *filter, const int16_t *filterPos, long filterSize, int shift)
 +{
-     const enum PixelFormat srcFormat= c->srcFormat;
-     const enum PixelFormat dstFormat= c->dstFormat;
-     const int srcBpp= (c->srcFormatBpp + 7) >> 3;
-     const int dstBpp= (c->dstFormatBpp + 7) >> 3;
-     const int srcId= c->srcFormatBpp >> 2; /* 1:0, 4:1, 8:2, 15:3, 16:4, 24:6, 32:8 */
-     const int dstId= c->dstFormatBpp >> 2;
-     void (*conv)(const uint8_t *src, uint8_t *dst, int src_size)=NULL;
- #define CONV_IS(src, dst) (srcFormat == PIX_FMT_##src && dstFormat == PIX_FMT_##dst)
-     if (isRGBA32(srcFormat) && isRGBA32(dstFormat)) {
-         if (     CONV_IS(ABGR, RGBA)
-               || CONV_IS(ARGB, BGRA)
-               || CONV_IS(BGRA, ARGB)
-               || CONV_IS(RGBA, ABGR)) conv = shuffle_bytes_3210;
-         else if (CONV_IS(ABGR, ARGB)
-               || CONV_IS(ARGB, ABGR)) conv = shuffle_bytes_0321;
-         else if (CONV_IS(ABGR, BGRA)
-               || CONV_IS(ARGB, RGBA)) conv = shuffle_bytes_1230;
-         else if (CONV_IS(BGRA, RGBA)
-               || CONV_IS(RGBA, BGRA)) conv = shuffle_bytes_2103;
-         else if (CONV_IS(BGRA, ABGR)
-               || CONV_IS(RGBA, ARGB)) conv = shuffle_bytes_3012;
-     } else
-     /* BGR -> BGR */
-     if (  (isBGRinInt(srcFormat) && isBGRinInt(dstFormat))
-        || (isRGBinInt(srcFormat) && isRGBinInt(dstFormat))) {
-         switch(srcId | (dstId<<4)) {
-         case 0x34: conv= rgb16to15; break;
-         case 0x36: conv= rgb24to15; break;
-         case 0x38: conv= rgb32to15; break;
-         case 0x43: conv= rgb15to16; break;
-         case 0x46: conv= rgb24to16; break;
-         case 0x48: conv= rgb32to16; break;
-         case 0x63: conv= rgb15to24; break;
-         case 0x64: conv= rgb16to24; break;
-         case 0x68: conv= rgb32to24; break;
-         case 0x83: conv= rgb15to32; break;
-         case 0x84: conv= rgb16to32; break;
-         case 0x86: conv= rgb24to32; break;
-         }
-     } else if (  (isBGRinInt(srcFormat) && isRGBinInt(dstFormat))
-              || (isRGBinInt(srcFormat) && isBGRinInt(dstFormat))) {
-         switch(srcId | (dstId<<4)) {
-         case 0x33: conv= rgb15tobgr15; break;
-         case 0x34: conv= rgb16tobgr15; break;
-         case 0x36: conv= rgb24tobgr15; break;
-         case 0x38: conv= rgb32tobgr15; break;
-         case 0x43: conv= rgb15tobgr16; break;
-         case 0x44: conv= rgb16tobgr16; break;
-         case 0x46: conv= rgb24tobgr16; break;
-         case 0x48: conv= rgb32tobgr16; break;
-         case 0x63: conv= rgb15tobgr24; break;
-         case 0x64: conv= rgb16tobgr24; break;
-         case 0x66: conv= rgb24tobgr24; break;
-         case 0x68: conv= rgb32tobgr24; break;
-         case 0x83: conv= rgb15tobgr32; break;
-         case 0x84: conv= rgb16tobgr32; break;
-         case 0x86: conv= rgb24tobgr32; break;
++    int i, j;
++    for (i=0; i<dstW; i++) {
++        int srcPos= filterPos[i];
++        int val=0;
++        for (j=0; j<filterSize; j++) {
++            val += ((int)av_bswap16(src[srcPos + j]))*filter[filterSize*i + j];
 +        }
++        dst[i] = FFMIN(val>>shift, (1<<15)-1); // the cubic equation does overflow ...
 +    }
++}
 +
-     if (!conv) {
-         av_log(c, AV_LOG_ERROR, "internal error %s -> %s converter\n",
-                av_get_pix_fmt_name(srcFormat), av_get_pix_fmt_name(dstFormat));
-     } else {
-         const uint8_t *srcPtr= src[0];
-               uint8_t *dstPtr= dst[0];
-         if ((srcFormat == PIX_FMT_RGB32_1 || srcFormat == PIX_FMT_BGR32_1) && !isRGBA32(dstFormat))
-             srcPtr += ALT32_CORR;
-         if ((dstFormat == PIX_FMT_RGB32_1 || dstFormat == PIX_FMT_BGR32_1) && !isRGBA32(srcFormat))
-             dstPtr += ALT32_CORR;
-         if (dstStride[0]*srcBpp == srcStride[0]*dstBpp && srcStride[0] > 0 && !(srcStride[0]%srcBpp))
-             conv(srcPtr, dstPtr + dstStride[0]*srcSliceY, srcSliceH*srcStride[0]);
-         else {
-             int i;
-             dstPtr += dstStride[0]*srcSliceY;
-             for (i=0; i<srcSliceH; i++) {
-                 conv(srcPtr, dstPtr, c->srcW*srcBpp);
-                 srcPtr+= srcStride[0];
-                 dstPtr+= dstStride[0];
-             }
-         }
+ //FIXME all pal and rgb srcFormats could do this convertion as well
+ //FIXME all scalers more complex than bilinear could do half of this transform
 -static void chrRangeToJpeg_c(uint16_t *dstU, uint16_t *dstV, int width)
++static void chrRangeToJpeg_c(int16_t *dstU, int16_t *dstV, int width)
+ {
+     int i;
+     for (i = 0; i < width; i++) {
+         dstU[i] = (FFMIN(dstU[i],30775)*4663 - 9289992)>>12; //-264
+         dstV[i] = (FFMIN(dstV[i],30775)*4663 - 9289992)>>12; //-264
      }
-     return srcSliceH;
  }
- static int bgr24ToYv12Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
-                               int srcSliceH, uint8_t* dst[], int dstStride[])
 -static void chrRangeFromJpeg_c(uint16_t *dstU, uint16_t *dstV, int width)
++static void chrRangeFromJpeg_c(int16_t *dstU, int16_t *dstV, int width)
  {
-     rgb24toyv12(
-         src[0],
-         dst[0]+ srcSliceY    *dstStride[0],
-         dst[1]+(srcSliceY>>1)*dstStride[1],
-         dst[2]+(srcSliceY>>1)*dstStride[2],
-         c->srcW, srcSliceH,
-         dstStride[0], dstStride[1], srcStride[0]);
-     if (dst[3])
-         fillPlane(dst[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255);
-     return srcSliceH;
+     int i;
+     for (i = 0; i < width; i++) {
+         dstU[i] = (dstU[i]*1799 + 4081085)>>11; //1469
+         dstV[i] = (dstV[i]*1799 + 4081085)>>11; //1469
+     }
  }
- static int yvu9ToYv12Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
-                              int srcSliceH, uint8_t* dst[], int dstStride[])
 -static void lumRangeToJpeg_c(uint16_t *dst, int width)
++static void lumRangeToJpeg_c(int16_t *dst, int width)
  {
-     copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW,
-               dst[0], dstStride[0]);
-     planar2x(src[1], dst[1] + dstStride[1]*(srcSliceY >> 1), c->chrSrcW,
-              srcSliceH >> 2, srcStride[1], dstStride[1]);
-     planar2x(src[2], dst[2] + dstStride[2]*(srcSliceY >> 1), c->chrSrcW,
-              srcSliceH >> 2, srcStride[2], dstStride[2]);
-     if (dst[3])
-         fillPlane(dst[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255);
-     return srcSliceH;
+     int i;
+     for (i = 0; i < width; i++)
+         dst[i] = (FFMIN(dst[i],30189)*19077 - 39057361)>>14;
+ }
 -static void lumRangeFromJpeg_c(uint16_t *dst, int width)
++static void lumRangeFromJpeg_c(int16_t *dst, int width)
+ {
+     int i;
+     for (i = 0; i < width; i++)
+         dst[i] = (dst[i]*14071 + 33561947)>>14;
  }
  
- /* unscaled copy like stuff (assumes nearly identical formats) */
- static int packedCopyWrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
-                              int srcSliceH, uint8_t* dst[], int dstStride[])
+ static void hyscale_fast_c(SwsContext *c, int16_t *dst, int dstWidth,
+                            const uint8_t *src, int srcW, int xInc)
  {
-     if (dstStride[0]==srcStride[0] && srcStride[0] > 0)
-         memcpy(dst[0] + dstStride[0]*srcSliceY, src[0], srcSliceH*dstStride[0]);
-     else {
-         int i;
-         const uint8_t *srcPtr= src[0];
-         uint8_t *dstPtr= dst[0] + dstStride[0]*srcSliceY;
-         int length=0;
-         /* universal length finder */
-         while(length+c->srcW <= FFABS(dstStride[0])
-            && length+c->srcW <= FFABS(srcStride[0])) length+= c->srcW;
-         assert(length!=0);
-         for (i=0; i<srcSliceH; i++) {
-             memcpy(dstPtr, srcPtr, length);
-             srcPtr+= srcStride[0];
-             dstPtr+= dstStride[0];
-         }
+     int i;
+     unsigned int xpos=0;
+     for (i=0;i<dstWidth;i++) {
+         register unsigned int xx=xpos>>16;
+         register unsigned int xalpha=(xpos&0xFFFF)>>9;
+         dst[i]= (src[xx]<<7) + (src[xx+1] - src[xx])*xalpha;
+         xpos+=xInc;
      }
-     return srcSliceH;
++    for (i=dstWidth-1; (i*xInc)>>16 >=srcW-1; i--)
++        dst[i] = src[srcW-1]*128;
  }
  
- #define DITHER_COPY(dst, dstStride, src, srcStride, bswap, dbswap)\
-     uint16_t scale= dither_scale[dst_depth-1][src_depth-1];\
-     int shift= src_depth-dst_depth + dither_scale[src_depth-2][dst_depth-1];\
-     for (i = 0; i < height; i++) {\
-         const uint8_t *dither= dithers[src_depth-9][i&7];\
-         for (j = 0; j < length-7; j+=8){\
-             dst[j+0] = dbswap((bswap(src[j+0]) + dither[0])*scale>>shift);\
-             dst[j+1] = dbswap((bswap(src[j+1]) + dither[1])*scale>>shift);\
-             dst[j+2] = dbswap((bswap(src[j+2]) + dither[2])*scale>>shift);\
-             dst[j+3] = dbswap((bswap(src[j+3]) + dither[3])*scale>>shift);\
-             dst[j+4] = dbswap((bswap(src[j+4]) + dither[4])*scale>>shift);\
-             dst[j+5] = dbswap((bswap(src[j+5]) + dither[5])*scale>>shift);\
-             dst[j+6] = dbswap((bswap(src[j+6]) + dither[6])*scale>>shift);\
-             dst[j+7] = dbswap((bswap(src[j+7]) + dither[7])*scale>>shift);\
-         }\
-         for (; j < length; j++)\
-             dst[j] = dbswap((bswap(src[j]) + dither[j&7])*scale>>shift);\
-         dst += dstStride;\
-         src += srcStride;\
-     }
+ // *** horizontal scale Y line to temp buffer
+ static inline void hyscale(SwsContext *c, uint16_t *dst, int dstWidth,
+                            const uint8_t *src, int srcW, int xInc,
+                            const int16_t *hLumFilter,
+                            const int16_t *hLumFilterPos, int hLumFilterSize,
+                            uint8_t *formatConvBuffer,
+                            uint32_t *pal, int isAlpha)
+ {
+     void (*toYV12)(uint8_t *, const uint8_t *, int, uint32_t *) = isAlpha ? c->alpToYV12 : c->lumToYV12;
 -    void (*convertRange)(uint16_t *, int) = isAlpha ? NULL : c->lumConvertRange;
++    void (*convertRange)(int16_t *, int) = isAlpha ? NULL : c->lumConvertRange;
  
+     src += isAlpha ? c->alpSrcOffset : c->lumSrcOffset;
  
- static int planarCopyWrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
-                              int srcSliceH, uint8_t* dst[], int dstStride[])
- {
-     int plane, i, j;
-     for (plane=0; plane<4; plane++) {
-         int length= (plane==0 || plane==3) ? c->srcW  : -((-c->srcW  )>>c->chrDstHSubSample);
-         int y=      (plane==0 || plane==3) ? srcSliceY: -((-srcSliceY)>>c->chrDstVSubSample);
-         int height= (plane==0 || plane==3) ? srcSliceH: -((-srcSliceH)>>c->chrDstVSubSample);
-         const uint8_t *srcPtr= src[plane];
-         uint8_t *dstPtr= dst[plane] + dstStride[plane]*y;
-         if (!dst[plane]) continue;
-         // ignore palette for GRAY8
-         if (plane == 1 && !dst[2]) continue;
-         if (!src[plane] || (plane == 1 && !src[2])) {
-             if(is16BPS(c->dstFormat))
-                 length*=2;
-             fillPlane(dst[plane], dstStride[plane], length, height, y, (plane==3) ? 255 : 128);
-         } else {
-             if(isNBPS(c->srcFormat) || isNBPS(c->dstFormat)
-                || (is16BPS(c->srcFormat) != is16BPS(c->dstFormat))
-             ) {
-                 const int src_depth = av_pix_fmt_descriptors[c->srcFormat].comp[plane].depth_minus1+1;
-                 const int dst_depth = av_pix_fmt_descriptors[c->dstFormat].comp[plane].depth_minus1+1;
-                 const uint16_t *srcPtr2 = (const uint16_t*)srcPtr;
-                 uint16_t *dstPtr2 = (uint16_t*)dstPtr;
-                 if (dst_depth == 8) {
-                     if(isBE(c->srcFormat) == HAVE_BIGENDIAN){
-                         DITHER_COPY(dstPtr, dstStride[plane], srcPtr2, srcStride[plane]/2, , )
-                     } else {
-                         DITHER_COPY(dstPtr, dstStride[plane], srcPtr2, srcStride[plane]/2, av_bswap16, )
-                     }
-                 } else if (src_depth == 8) {
-                     for (i = 0; i < height; i++) {
-                         if(isBE(c->dstFormat)){
-                             for (j = 0; j < length; j++)
-                                 AV_WB16(&dstPtr2[j], (srcPtr[j]<<(dst_depth-8)) |
-                                                      (srcPtr[j]>>(2*8-dst_depth)));
-                         } else {
-                             for (j = 0; j < length; j++)
-                                 AV_WL16(&dstPtr2[j], (srcPtr[j]<<(dst_depth-8)) |
-                                                      (srcPtr[j]>>(2*8-dst_depth)));
-                         }
-                         dstPtr2 += dstStride[plane]/2;
-                         srcPtr  += srcStride[plane];
-                     }
-                 } else if (src_depth <= dst_depth) {
-                     for (i = 0; i < height; i++) {
- #define COPY_UP(r,w) \
-     for (j = 0; j < length; j++){ \
-         unsigned int v= r(&srcPtr2[j]);\
-         w(&dstPtr2[j], (v<<(dst_depth-src_depth)) | \
-                        (v>>(2*src_depth-dst_depth)));\
+     if (toYV12) {
+         toYV12(formatConvBuffer, src, srcW, pal);
+         src= formatConvBuffer;
      }
-                         if(isBE(c->srcFormat)){
-                             if(isBE(c->dstFormat)){
-                                 COPY_UP(AV_RB16, AV_WB16)
-                             } else {
-                                 COPY_UP(AV_RB16, AV_WL16)
-                             }
-                         } else {
-                             if(isBE(c->dstFormat)){
-                                 COPY_UP(AV_RL16, AV_WB16)
-                             } else {
-                                 COPY_UP(AV_RL16, AV_WL16)
-                             }
-                         }
-                         dstPtr2 += dstStride[plane]/2;
-                         srcPtr2 += srcStride[plane]/2;
-                     }
-                 } else {
-                     if(isBE(c->srcFormat) == HAVE_BIGENDIAN){
-                         if(isBE(c->dstFormat) == HAVE_BIGENDIAN){
-                             DITHER_COPY(dstPtr2, dstStride[plane]/2, srcPtr2, srcStride[plane]/2, , )
-                         } else {
-                             DITHER_COPY(dstPtr2, dstStride[plane]/2, srcPtr2, srcStride[plane]/2, , av_bswap16)
-                         }
-                     }else{
-                         if(isBE(c->dstFormat) == HAVE_BIGENDIAN){
-                             DITHER_COPY(dstPtr2, dstStride[plane]/2, srcPtr2, srcStride[plane]/2, av_bswap16, )
-                         } else {
-                             DITHER_COPY(dstPtr2, dstStride[plane]/2, srcPtr2, srcStride[plane]/2, av_bswap16, av_bswap16)
-                         }
-                     }
-                 }
-             } else if(is16BPS(c->srcFormat) && is16BPS(c->dstFormat)
-                   && isBE(c->srcFormat) != isBE(c->dstFormat)) {
-                 for (i=0; i<height; i++) {
-                     for (j=0; j<length; j++)
-                         ((uint16_t*)dstPtr)[j] = av_bswap16(((const uint16_t*)srcPtr)[j]);
-                     srcPtr+= srcStride[plane];
-                     dstPtr+= dstStride[plane];
-                 }
-             } else if (dstStride[plane] == srcStride[plane] &&
-                        srcStride[plane] > 0 && srcStride[plane] == length) {
-                 memcpy(dst[plane] + dstStride[plane]*y, src[plane],
-                        height*dstStride[plane]);
-             } else {
-                 if(is16BPS(c->srcFormat) && is16BPS(c->dstFormat))
-                     length*=2;
-                 for (i=0; i<height; i++) {
-                     memcpy(dstPtr, srcPtr, length);
-                     srcPtr+= srcStride[plane];
-                     dstPtr+= dstStride[plane];
-                 }
-             }
-         }
 -    if (!c->hyscale_fast) {
++    if (c->hScale16) {
++        int shift= isAnyRGB(c->srcFormat) || c->srcFormat==PIX_FMT_PAL8 ? 13 : av_pix_fmt_descriptors[c->srcFormat].comp[0].depth_minus1;
++        c->hScale16(dst, dstWidth, (const uint16_t*)src, srcW, xInc, hLumFilter, hLumFilterPos, hLumFilterSize, shift);
++    } else if (!c->hyscale_fast) {
+         c->hScale(dst, dstWidth, src, srcW, xInc, hLumFilter, hLumFilterPos, hLumFilterSize);
+     } else { // fast bilinear upscale / crap downscale
+         c->hyscale_fast(c, dst, dstWidth, src, srcW, xInc);
      }
-     return srcSliceH;
+     if (convertRange)
+         convertRange(dst, dstWidth);
  }
  
- void ff_get_unscaled_swscale(SwsContext *c)
+ static void hcscale_fast_c(SwsContext *c, int16_t *dst1, int16_t *dst2,
+                            int dstWidth, const uint8_t *src1,
+                            const uint8_t *src2, int srcW, int xInc)
  {
-     const enum PixelFormat srcFormat = c->srcFormat;
-     const enum PixelFormat dstFormat = c->dstFormat;
-     const int flags = c->flags;
-     const int dstH = c->dstH;
-     int needsDither;
-     needsDither= isAnyRGB(dstFormat)
-         &&  c->dstFormatBpp < 24
-         && (c->dstFormatBpp < c->srcFormatBpp || (!isAnyRGB(srcFormat)));
-     /* yv12_to_nv12 */
-     if ((srcFormat == PIX_FMT_YUV420P || srcFormat == PIX_FMT_YUVA420P) && (dstFormat == PIX_FMT_NV12 || dstFormat == PIX_FMT_NV21)) {
-         c->swScale= planarToNv12Wrapper;
+     int i;
+     unsigned int xpos=0;
+     for (i=0;i<dstWidth;i++) {
+         register unsigned int xx=xpos>>16;
+         register unsigned int xalpha=(xpos&0xFFFF)>>9;
+         dst1[i]=(src1[xx]*(xalpha^127)+src1[xx+1]*xalpha);
+         dst2[i]=(src2[xx]*(xalpha^127)+src2[xx+1]*xalpha);
+         xpos+=xInc;
      }
-     /* yuv2bgr */
-     if ((srcFormat==PIX_FMT_YUV420P || srcFormat==PIX_FMT_YUV422P || srcFormat==PIX_FMT_YUVA420P) && isAnyRGB(dstFormat)
-         && !(flags & SWS_ACCURATE_RND) && !(dstH&1)) {
-         c->swScale= ff_yuv2rgb_get_func_ptr(c);
++    for (i=dstWidth-1; (i*xInc)>>16 >=srcW-1; i--) {
++        dst1[i] = src1[srcW-1]*128;
++        dst2[i] = src2[srcW-1]*128;
 +    }
+ }
  
-     if (srcFormat==PIX_FMT_YUV410P && (dstFormat==PIX_FMT_YUV420P || dstFormat==PIX_FMT_YUVA420P) && !(flags & SWS_BITEXACT)) {
-         c->swScale= yvu9ToYv12Wrapper;
-     }
+ static inline void hcscale(SwsContext *c, uint16_t *dst1, uint16_t *dst2, int dstWidth,
+                            const uint8_t *src1, const uint8_t *src2,
+                            int srcW, int xInc, const int16_t *hChrFilter,
+                            const int16_t *hChrFilterPos, int hChrFilterSize,
+                            uint8_t *formatConvBuffer, uint32_t *pal)
+ {
  
-     /* bgr24toYV12 */
-     if (srcFormat==PIX_FMT_BGR24 && (dstFormat==PIX_FMT_YUV420P || dstFormat==PIX_FMT_YUVA420P) && !(flags & SWS_ACCURATE_RND))
-         c->swScale= bgr24ToYv12Wrapper;
-     /* RGB/BGR -> RGB/BGR (no dither needed forms) */
-     if (   isAnyRGB(srcFormat)
-         && isAnyRGB(dstFormat)
-         && srcFormat != PIX_FMT_BGR8      && dstFormat != PIX_FMT_BGR8
-         && srcFormat != PIX_FMT_RGB8      && dstFormat != PIX_FMT_RGB8
-         && srcFormat != PIX_FMT_BGR4      && dstFormat != PIX_FMT_BGR4
-         && srcFormat != PIX_FMT_RGB4      && dstFormat != PIX_FMT_RGB4
-         && srcFormat != PIX_FMT_BGR4_BYTE && dstFormat != PIX_FMT_BGR4_BYTE
-         && srcFormat != PIX_FMT_RGB4_BYTE && dstFormat != PIX_FMT_RGB4_BYTE
-         && srcFormat != PIX_FMT_MONOBLACK && dstFormat != PIX_FMT_MONOBLACK
-         && srcFormat != PIX_FMT_MONOWHITE && dstFormat != PIX_FMT_MONOWHITE
-         && srcFormat != PIX_FMT_RGB48LE   && dstFormat != PIX_FMT_RGB48LE
-         && srcFormat != PIX_FMT_RGB48BE   && dstFormat != PIX_FMT_RGB48BE
-         && srcFormat != PIX_FMT_BGR48LE   && dstFormat != PIX_FMT_BGR48LE
-         && srcFormat != PIX_FMT_BGR48BE   && dstFormat != PIX_FMT_BGR48BE
-         && (!needsDither || (c->flags&(SWS_FAST_BILINEAR|SWS_POINT))))
-         c->swScale= rgbToRgbWrapper;
-     if ((usePal(srcFormat) && (
-         dstFormat == PIX_FMT_RGB32   ||
-         dstFormat == PIX_FMT_RGB32_1 ||
-         dstFormat == PIX_FMT_RGB24   ||
-         dstFormat == PIX_FMT_BGR32   ||
-         dstFormat == PIX_FMT_BGR32_1 ||
-         dstFormat == PIX_FMT_BGR24)))
-         c->swScale= palToRgbWrapper;
-     if (srcFormat == PIX_FMT_YUV422P) {
-         if (dstFormat == PIX_FMT_YUYV422)
-             c->swScale= yuv422pToYuy2Wrapper;
-         else if (dstFormat == PIX_FMT_UYVY422)
-             c->swScale= yuv422pToUyvyWrapper;
-     }
+     src1 += c->chrSrcOffset;
+     src2 += c->chrSrcOffset;
  
-     /* LQ converters if -sws 0 or -sws 4*/
-     if (c->flags&(SWS_FAST_BILINEAR|SWS_POINT)) {
-         /* yv12_to_yuy2 */
-         if (srcFormat == PIX_FMT_YUV420P || srcFormat == PIX_FMT_YUVA420P) {
-             if (dstFormat == PIX_FMT_YUYV422)
-                 c->swScale= planarToYuy2Wrapper;
-             else if (dstFormat == PIX_FMT_UYVY422)
-                 c->swScale= planarToUyvyWrapper;
-         }
-     }
-     if(srcFormat == PIX_FMT_YUYV422 && (dstFormat == PIX_FMT_YUV420P || dstFormat == PIX_FMT_YUVA420P))
-         c->swScale= yuyvToYuv420Wrapper;
-     if(srcFormat == PIX_FMT_UYVY422 && (dstFormat == PIX_FMT_YUV420P || dstFormat == PIX_FMT_YUVA420P))
-         c->swScale= uyvyToYuv420Wrapper;
-     if(srcFormat == PIX_FMT_YUYV422 && dstFormat == PIX_FMT_YUV422P)
-         c->swScale= yuyvToYuv422Wrapper;
-     if(srcFormat == PIX_FMT_UYVY422 && dstFormat == PIX_FMT_YUV422P)
-         c->swScale= uyvyToYuv422Wrapper;
- #if HAVE_ALTIVEC
-     if ((av_get_cpu_flags() & AV_CPU_FLAG_ALTIVEC) &&
-         !(c->flags & SWS_BITEXACT) &&
-         srcFormat == PIX_FMT_YUV420P) {
-         // unscaled YV12 -> packed YUV, we want speed
-         if (dstFormat == PIX_FMT_YUYV422)
-             c->swScale= yv12toyuy2_unscaled_altivec;
-         else if (dstFormat == PIX_FMT_UYVY422)
-             c->swScale= yv12touyvy_unscaled_altivec;
+     if (c->chrToYV12) {
 -        uint8_t *buf2 = formatConvBuffer + FFALIGN(srcW, 16);
++        uint8_t *buf2 = formatConvBuffer + FFALIGN(srcW*2+78, 16);
+         c->chrToYV12(formatConvBuffer, buf2, src1, src2, srcW, pal);
+         src1= formatConvBuffer;
+         src2= buf2;
      }
- #endif
  
-     /* simple copy */
-     if (  srcFormat == dstFormat
-         || (srcFormat == PIX_FMT_YUVA420P && dstFormat == PIX_FMT_YUV420P)
-         || (srcFormat == PIX_FMT_YUV420P && dstFormat == PIX_FMT_YUVA420P)
-         || (isPlanarYUV(srcFormat) && isGray(dstFormat))
-         || (isPlanarYUV(dstFormat) && isGray(srcFormat))
-         || (isGray(dstFormat) && isGray(srcFormat))
-         || (isPlanarYUV(srcFormat) && isPlanarYUV(dstFormat)
-             && c->chrDstHSubSample == c->chrSrcHSubSample
-             && c->chrDstVSubSample == c->chrSrcVSubSample
-             && dstFormat != PIX_FMT_NV12 && dstFormat != PIX_FMT_NV21
-             && srcFormat != PIX_FMT_NV12 && srcFormat != PIX_FMT_NV21))
-     {
-         if (isPacked(c->srcFormat))
-             c->swScale= packedCopyWrapper;
-         else /* Planar YUV or gray */
-             c->swScale= planarCopyWrapper;
 -    if (!c->hcscale_fast) {
++    if (c->hScale16) {
++        int shift= isAnyRGB(c->srcFormat) || c->srcFormat==PIX_FMT_PAL8 ? 13 : av_pix_fmt_descriptors[c->srcFormat].comp[0].depth_minus1;
++        c->hScale16(dst1, dstWidth, (const uint16_t*)src1, srcW, xInc, hChrFilter, hChrFilterPos, hChrFilterSize, shift);
++        c->hScale16(dst2, dstWidth, (const uint16_t*)src2, srcW, xInc, hChrFilter, hChrFilterPos, hChrFilterSize, shift);
++    } else if (!c->hcscale_fast) {
+         c->hScale(dst1, dstWidth, src1, srcW, xInc, hChrFilter, hChrFilterPos, hChrFilterSize);
+         c->hScale(dst2, dstWidth, src2, srcW, xInc, hChrFilter, hChrFilterPos, hChrFilterSize);
+     } else { // fast bilinear upscale / crap downscale
+         c->hcscale_fast(c, dst1, dst2, dstWidth, src1, src2, srcW, xInc);
      }
- #if ARCH_BFIN
-     ff_bfin_get_unscaled_swscale (c);
- #endif
+     if (c->chrConvertRange)
+         c->chrConvertRange(dst1, dst2, dstWidth);
  }
  
- static void reset_ptr(const uint8_t* src[], int format)
+ #define DEBUG_SWSCALE_BUFFERS 0
+ #define DEBUG_BUFFERS(...) if (DEBUG_SWSCALE_BUFFERS) av_log(c, AV_LOG_DEBUG, __VA_ARGS__)
+ static int swScale(SwsContext *c, const uint8_t* src[],
+                    int srcStride[], int srcSliceY,
+                    int srcSliceH, uint8_t* dst[], int dstStride[])
  {
-     if(!isALPHA(format))
-         src[3]=NULL;
-     if(!isPlanarYUV(format)) {
-         src[3]=src[2]=NULL;
+     /* load a few things into local vars to make the code more readable? and faster */
+     const int srcW= c->srcW;
+     const int dstW= c->dstW;
+     const int dstH= c->dstH;
+     const int chrDstW= c->chrDstW;
+     const int chrSrcW= c->chrSrcW;
+     const int lumXInc= c->lumXInc;
+     const int chrXInc= c->chrXInc;
+     const enum PixelFormat dstFormat= c->dstFormat;
+     const int flags= c->flags;
+     int16_t *vLumFilterPos= c->vLumFilterPos;
+     int16_t *vChrFilterPos= c->vChrFilterPos;
+     int16_t *hLumFilterPos= c->hLumFilterPos;
+     int16_t *hChrFilterPos= c->hChrFilterPos;
+     int16_t *vLumFilter= c->vLumFilter;
+     int16_t *vChrFilter= c->vChrFilter;
+     int16_t *hLumFilter= c->hLumFilter;
+     int16_t *hChrFilter= c->hChrFilter;
+     int32_t *lumMmxFilter= c->lumMmxFilter;
+     int32_t *chrMmxFilter= c->chrMmxFilter;
+     int32_t av_unused *alpMmxFilter= c->alpMmxFilter;
+     const int vLumFilterSize= c->vLumFilterSize;
+     const int vChrFilterSize= c->vChrFilterSize;
+     const int hLumFilterSize= c->hLumFilterSize;
+     const int hChrFilterSize= c->hChrFilterSize;
+     int16_t **lumPixBuf= c->lumPixBuf;
+     int16_t **chrUPixBuf= c->chrUPixBuf;
+     int16_t **chrVPixBuf= c->chrVPixBuf;
+     int16_t **alpPixBuf= c->alpPixBuf;
+     const int vLumBufSize= c->vLumBufSize;
+     const int vChrBufSize= c->vChrBufSize;
+     uint8_t *formatConvBuffer= c->formatConvBuffer;
+     const int chrSrcSliceY= srcSliceY >> c->chrSrcVSubSample;
+     const int chrSrcSliceH= -((-srcSliceH) >> c->chrSrcVSubSample);
+     int lastDstY;
+     uint32_t *pal=c->pal_yuv;
+     /* vars which will change and which we need to store back in the context */
+     int dstY= c->dstY;
+     int lumBufIndex= c->lumBufIndex;
+     int chrBufIndex= c->chrBufIndex;
+     int lastInLumBuf= c->lastInLumBuf;
+     int lastInChrBuf= c->lastInChrBuf;
+     if (isPacked(c->srcFormat)) {
+         src[0]=
+         src[1]=
+         src[2]=
+         src[3]= src[0];
+         srcStride[0]=
+         srcStride[1]=
+         srcStride[2]=
+         srcStride[3]= srcStride[0];
+     }
+     srcStride[1]<<= c->vChrDrop;
+     srcStride[2]<<= c->vChrDrop;
+     DEBUG_BUFFERS("swScale() %p[%d] %p[%d] %p[%d] %p[%d] -> %p[%d] %p[%d] %p[%d] %p[%d]\n",
+                   src[0], srcStride[0], src[1], srcStride[1], src[2], srcStride[2], src[3], srcStride[3],
+                   dst[0], dstStride[0], dst[1], dstStride[1], dst[2], dstStride[2], dst[3], dstStride[3]);
+     DEBUG_BUFFERS("srcSliceY: %d srcSliceH: %d dstY: %d dstH: %d\n",
+                    srcSliceY,    srcSliceH,    dstY,    dstH);
+     DEBUG_BUFFERS("vLumFilterSize: %d vLumBufSize: %d vChrFilterSize: %d vChrBufSize: %d\n",
+                    vLumFilterSize,    vLumBufSize,    vChrFilterSize,    vChrBufSize);
+     if (dstStride[0]%8 !=0 || dstStride[1]%8 !=0 || dstStride[2]%8 !=0 || dstStride[3]%8 != 0) {
+         static int warnedAlready=0; //FIXME move this into the context perhaps
+         if (flags & SWS_PRINT_INFO && !warnedAlready) {
+             av_log(c, AV_LOG_WARNING, "Warning: dstStride is not aligned!\n"
+                    "         ->cannot do aligned memory accesses anymore\n");
+             warnedAlready=1;
+         }
+     }
  
-         if (!usePal(format))
-             src[1]= NULL;
+     /* Note the user might start scaling the picture in the middle so this
+        will not get executed. This is not really intended but works
+        currently, so people might do it. */
+     if (srcSliceY ==0) {
+         lumBufIndex=-1;
+         chrBufIndex=-1;
+         dstY=0;
+         lastInLumBuf= -1;
+         lastInChrBuf= -1;
      }
- }
  
- static int check_image_pointers(uint8_t *data[4], enum PixelFormat pix_fmt,
-                                 const int linesizes[4])
- {
-     const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[pix_fmt];
-     int i;
+     lastDstY= dstY;
+     for (;dstY < dstH; dstY++) {
+         unsigned char *dest =dst[0]+dstStride[0]*dstY;
+         const int chrDstY= dstY>>c->chrDstVSubSample;
+         unsigned char *uDest=dst[1]+dstStride[1]*chrDstY;
+         unsigned char *vDest=dst[2]+dstStride[2]*chrDstY;
+         unsigned char *aDest=(CONFIG_SWSCALE_ALPHA && alpPixBuf) ? dst[3]+dstStride[3]*dstY : NULL;
++        const uint8_t *lumDither= isNBPS(c->srcFormat) || is16BPS(c->srcFormat) ? dithers[7][dstY   &7] : flat64;
++        const uint8_t *chrDither= isNBPS(c->srcFormat) || is16BPS(c->srcFormat) ? dithers[7][chrDstY&7] : flat64;
+         const int firstLumSrcY= vLumFilterPos[dstY]; //First line needed as input
+         const int firstLumSrcY2= vLumFilterPos[FFMIN(dstY | ((1<<c->chrDstVSubSample) - 1), dstH-1)];
+         const int firstChrSrcY= vChrFilterPos[chrDstY]; //First line needed as input
+         int lastLumSrcY= firstLumSrcY + vLumFilterSize -1; // Last line needed as input
+         int lastLumSrcY2=firstLumSrcY2+ vLumFilterSize -1; // Last line needed as input
+         int lastChrSrcY= firstChrSrcY + vChrFilterSize -1; // Last line needed as input
+         int enough_lines;
+         //handle holes (FAST_BILINEAR & weird filters)
+         if (firstLumSrcY > lastInLumBuf) lastInLumBuf= firstLumSrcY-1;
+         if (firstChrSrcY > lastInChrBuf) lastInChrBuf= firstChrSrcY-1;
+         assert(firstLumSrcY >= lastInLumBuf - vLumBufSize + 1);
+         assert(firstChrSrcY >= lastInChrBuf - vChrBufSize + 1);
+         DEBUG_BUFFERS("dstY: %d\n", dstY);
+         DEBUG_BUFFERS("\tfirstLumSrcY: %d lastLumSrcY: %d lastInLumBuf: %d\n",
+                          firstLumSrcY,    lastLumSrcY,    lastInLumBuf);
+         DEBUG_BUFFERS("\tfirstChrSrcY: %d lastChrSrcY: %d lastInChrBuf: %d\n",
+                          firstChrSrcY,    lastChrSrcY,    lastInChrBuf);
+         // Do we have enough lines in this slice to output the dstY line
+         enough_lines = lastLumSrcY2 < srcSliceY + srcSliceH && lastChrSrcY < -((-srcSliceY - srcSliceH)>>c->chrSrcVSubSample);
+         if (!enough_lines) {
+             lastLumSrcY = srcSliceY + srcSliceH - 1;
+             lastChrSrcY = chrSrcSliceY + chrSrcSliceH - 1;
+             DEBUG_BUFFERS("buffering slice: lastLumSrcY %d lastChrSrcY %d\n",
+                                             lastLumSrcY, lastChrSrcY);
+         }
  
-     for (i = 0; i < 4; i++) {
-         int plane = desc->comp[i].plane;
-         if (!data[plane] || !linesizes[plane])
-             return 0;
+         //Do horizontal scaling
+         while(lastInLumBuf < lastLumSrcY) {
+             const uint8_t *src1= src[0]+(lastInLumBuf + 1 - srcSliceY)*srcStride[0];
+             const uint8_t *src2= src[3]+(lastInLumBuf + 1 - srcSliceY)*srcStride[3];
+             lumBufIndex++;
+             assert(lumBufIndex < 2*vLumBufSize);
+             assert(lastInLumBuf + 1 - srcSliceY < srcSliceH);
+             assert(lastInLumBuf + 1 - srcSliceY >= 0);
+             hyscale(c, lumPixBuf[ lumBufIndex ], dstW, src1, srcW, lumXInc,
+                     hLumFilter, hLumFilterPos, hLumFilterSize,
+                     formatConvBuffer,
+                     pal, 0);
+             if (CONFIG_SWSCALE_ALPHA && alpPixBuf)
+                 hyscale(c, alpPixBuf[ lumBufIndex ], dstW, src2, srcW,
+                         lumXInc, hLumFilter, hLumFilterPos, hLumFilterSize,
+                         formatConvBuffer,
+                         pal, 1);
+             lastInLumBuf++;
+             DEBUG_BUFFERS("\t\tlumBufIndex %d: lastInLumBuf: %d\n",
+                                lumBufIndex,    lastInLumBuf);
+         }
+         while(lastInChrBuf < lastChrSrcY) {
+             const uint8_t *src1= src[1]+(lastInChrBuf + 1 - chrSrcSliceY)*srcStride[1];
+             const uint8_t *src2= src[2]+(lastInChrBuf + 1 - chrSrcSliceY)*srcStride[2];
+             chrBufIndex++;
+             assert(chrBufIndex < 2*vChrBufSize);
+             assert(lastInChrBuf + 1 - chrSrcSliceY < (chrSrcSliceH));
+             assert(lastInChrBuf + 1 - chrSrcSliceY >= 0);
+             //FIXME replace parameters through context struct (some at least)
+             if (c->needs_hcscale)
+                 hcscale(c, chrUPixBuf[chrBufIndex], chrVPixBuf[chrBufIndex],
+                           chrDstW, src1, src2, chrSrcW, chrXInc,
+                           hChrFilter, hChrFilterPos, hChrFilterSize,
+                           formatConvBuffer, pal);
+             lastInChrBuf++;
+             DEBUG_BUFFERS("\t\tchrBufIndex %d: lastInChrBuf: %d\n",
+                                chrBufIndex,    lastInChrBuf);
+         }
+         //wrap buf index around to stay inside the ring buffer
+         if (lumBufIndex >= vLumBufSize) lumBufIndex-= vLumBufSize;
+         if (chrBufIndex >= vChrBufSize) chrBufIndex-= vChrBufSize;
+         if (!enough_lines)
+             break; //we can't output a dstY line so let's try with the next slice
+ #if HAVE_MMX
+         updateMMXDitherTables(c, dstY, lumBufIndex, chrBufIndex, lastInLumBuf, lastInChrBuf);
+ #endif
+         if (dstY < dstH-2) {
+             const int16_t **lumSrcPtr= (const int16_t **) lumPixBuf + lumBufIndex + firstLumSrcY - lastInLumBuf + vLumBufSize;
+             const int16_t **chrUSrcPtr= (const int16_t **) chrUPixBuf + chrBufIndex + firstChrSrcY - lastInChrBuf + vChrBufSize;
+             const int16_t **chrVSrcPtr= (const int16_t **) chrVPixBuf + chrBufIndex + firstChrSrcY - lastInChrBuf + vChrBufSize;
+             const int16_t **alpSrcPtr= (CONFIG_SWSCALE_ALPHA && alpPixBuf) ? (const int16_t **) alpPixBuf + lumBufIndex + firstLumSrcY - lastInLumBuf + vLumBufSize : NULL;
+             if (dstFormat == PIX_FMT_NV12 || dstFormat == PIX_FMT_NV21) {
+                 const int chrSkipMask= (1<<c->chrDstVSubSample)-1;
+                 if (dstY&chrSkipMask) uDest= NULL; //FIXME split functions in lumi / chromi
+                 c->yuv2nv12X(c,
+                              vLumFilter+dstY*vLumFilterSize   , lumSrcPtr, vLumFilterSize,
+                              vChrFilter+chrDstY*vChrFilterSize, chrUSrcPtr, chrVSrcPtr, vChrFilterSize,
 -                             dest, uDest, dstW, chrDstW, dstFormat);
++                             dest, uDest, dstW, chrDstW, dstFormat, lumDither, chrDither);
+             } else if (isPlanarYUV(dstFormat) || dstFormat==PIX_FMT_GRAY8) { //YV12 like
+                 const int chrSkipMask= (1<<c->chrDstVSubSample)-1;
+                 if ((dstY&chrSkipMask) || isGray(dstFormat)) uDest=vDest= NULL; //FIXME split functions in lumi / chromi
 -                if (is16BPS(dstFormat) || is9_OR_10BPS(dstFormat)) {
++                if (is16BPS(dstFormat) || isNBPS(dstFormat)) {
+                     yuv2yuvX16_c(vLumFilter+dstY*vLumFilterSize   , lumSrcPtr, vLumFilterSize,
+                                  vChrFilter+chrDstY*vChrFilterSize, chrUSrcPtr,
+                                  chrVSrcPtr, vChrFilterSize,
+                                  alpSrcPtr, (uint16_t *) dest, (uint16_t *) uDest,
+                                  (uint16_t *) vDest, (uint16_t *) aDest, dstW, chrDstW,
+                                  dstFormat);
+                 } else if (vLumFilterSize == 1 && vChrFilterSize == 1) { // unscaled YV12
+                     const int16_t *lumBuf = lumSrcPtr[0];
+                     const int16_t *chrUBuf= chrUSrcPtr[0];
+                     const int16_t *chrVBuf= chrVSrcPtr[0];
+                     const int16_t *alpBuf= (CONFIG_SWSCALE_ALPHA && alpPixBuf) ? alpSrcPtr[0] : NULL;
+                     c->yuv2yuv1(c, lumBuf, chrUBuf, chrVBuf, alpBuf, dest,
 -                                uDest, vDest, aDest, dstW, chrDstW);
++                                uDest, vDest, aDest, dstW, chrDstW, lumDither, chrDither);
+                 } else { //General YV12
+                     c->yuv2yuvX(c,
+                                 vLumFilter+dstY*vLumFilterSize   , lumSrcPtr, vLumFilterSize,
+                                 vChrFilter+chrDstY*vChrFilterSize, chrUSrcPtr,
+                                 chrVSrcPtr, vChrFilterSize,
 -                                alpSrcPtr, dest, uDest, vDest, aDest, dstW, chrDstW);
++                                alpSrcPtr, dest, uDest, vDest, aDest, dstW, chrDstW, lumDither, chrDither);
+                 }
+             } else {
+                 assert(lumSrcPtr  + vLumFilterSize - 1 < lumPixBuf  + vLumBufSize*2);
+                 assert(chrUSrcPtr + vChrFilterSize - 1 < chrUPixBuf + vChrBufSize*2);
+                 if (vLumFilterSize == 1 && vChrFilterSize == 2) { //unscaled RGB
+                     int chrAlpha= vChrFilter[2*dstY+1];
+                     if(flags & SWS_FULL_CHR_H_INT) {
+                         yuv2rgbX_c_full(c, //FIXME write a packed1_full function
+                                         vLumFilter+dstY*vLumFilterSize, lumSrcPtr, vLumFilterSize,
+                                         vChrFilter+dstY*vChrFilterSize, chrUSrcPtr,
+                                         chrVSrcPtr, vChrFilterSize,
+                                         alpSrcPtr, dest, dstW, dstY);
+                     } else {
+                         c->yuv2packed1(c, *lumSrcPtr, *chrUSrcPtr, *(chrUSrcPtr+1),
+                                        *chrVSrcPtr, *(chrVSrcPtr+1),
+                                        alpPixBuf ? *alpSrcPtr : NULL,
+                                        dest, dstW, chrAlpha, dstFormat, flags, dstY);
+                     }
+                 } else if (vLumFilterSize == 2 && vChrFilterSize == 2) { //bilinear upscale RGB
+                     int lumAlpha= vLumFilter[2*dstY+1];
+                     int chrAlpha= vChrFilter[2*dstY+1];
+                     lumMmxFilter[2]=
+                     lumMmxFilter[3]= vLumFilter[2*dstY   ]*0x10001;
+                     chrMmxFilter[2]=
+                     chrMmxFilter[3]= vChrFilter[2*chrDstY]*0x10001;
+                     if(flags & SWS_FULL_CHR_H_INT) {
+                         yuv2rgbX_c_full(c, //FIXME write a packed2_full function
+                                         vLumFilter+dstY*vLumFilterSize, lumSrcPtr, vLumFilterSize,
+                                         vChrFilter+dstY*vChrFilterSize, chrUSrcPtr, chrVSrcPtr, vChrFilterSize,
+                                         alpSrcPtr, dest, dstW, dstY);
+                     } else {
+                         c->yuv2packed2(c, *lumSrcPtr, *(lumSrcPtr+1), *chrUSrcPtr, *(chrUSrcPtr+1),
+                                        *chrVSrcPtr, *(chrVSrcPtr+1),
+                                        alpPixBuf ? *alpSrcPtr : NULL, alpPixBuf ? *(alpSrcPtr+1) : NULL,
+                                        dest, dstW, lumAlpha, chrAlpha, dstY);
+                     }
+                 } else { //general RGB
+                     if(flags & SWS_FULL_CHR_H_INT) {
+                         yuv2rgbX_c_full(c,
+                                         vLumFilter+dstY*vLumFilterSize, lumSrcPtr, vLumFilterSize,
+                                         vChrFilter+dstY*vChrFilterSize, chrUSrcPtr, chrVSrcPtr, vChrFilterSize,
+                                         alpSrcPtr, dest, dstW, dstY);
+                     } else {
+                         c->yuv2packedX(c,
+                                        vLumFilter+dstY*vLumFilterSize, lumSrcPtr, vLumFilterSize,
+                                        vChrFilter+dstY*vChrFilterSize, chrUSrcPtr, chrVSrcPtr, vChrFilterSize,
+                                        alpSrcPtr, dest, dstW, dstY);
+                     }
+                 }
+             }
+         } else { // hmm looks like we can't use MMX here without overwriting this array's tail
+             const int16_t **lumSrcPtr= (const int16_t **)lumPixBuf + lumBufIndex + firstLumSrcY - lastInLumBuf + vLumBufSize;
+             const int16_t **chrUSrcPtr= (const int16_t **)chrUPixBuf + chrBufIndex + firstChrSrcY - lastInChrBuf + vChrBufSize;
+             const int16_t **chrVSrcPtr= (const int16_t **)chrVPixBuf + chrBufIndex + firstChrSrcY - lastInChrBuf + vChrBufSize;
+             const int16_t **alpSrcPtr= (CONFIG_SWSCALE_ALPHA && alpPixBuf) ? (const int16_t **)alpPixBuf + lumBufIndex + firstLumSrcY - lastInLumBuf + vLumBufSize : NULL;
+             if (dstFormat == PIX_FMT_NV12 || dstFormat == PIX_FMT_NV21) {
+                 const int chrSkipMask= (1<<c->chrDstVSubSample)-1;
+                 if (dstY&chrSkipMask) uDest= NULL; //FIXME split functions in lumi / chromi
+                 yuv2nv12X_c(c, vLumFilter+dstY*vLumFilterSize,
+                             lumSrcPtr, vLumFilterSize,
+                             vChrFilter+chrDstY*vChrFilterSize,
+                             chrUSrcPtr, chrVSrcPtr, vChrFilterSize,
 -                            dest, uDest, dstW, chrDstW, dstFormat);
++                            dest, uDest, dstW, chrDstW, dstFormat, lumDither, chrDither);
+             } else if (isPlanarYUV(dstFormat) || dstFormat==PIX_FMT_GRAY8) { //YV12
+                 const int chrSkipMask= (1<<c->chrDstVSubSample)-1;
+                 if ((dstY&chrSkipMask) || isGray(dstFormat)) uDest=vDest= NULL; //FIXME split functions in lumi / chromi
+                 if (is16BPS(dstFormat) || is9_OR_10BPS(dstFormat)) {
+                     yuv2yuvX16_c(vLumFilter+dstY*vLumFilterSize   , lumSrcPtr, vLumFilterSize,
+                                  vChrFilter+chrDstY*vChrFilterSize, chrUSrcPtr, chrVSrcPtr, vChrFilterSize,
+                                  alpSrcPtr, (uint16_t *) dest, (uint16_t *) uDest, (uint16_t *) vDest, (uint16_t *) aDest, dstW, chrDstW,
+                                  dstFormat);
+                 } else {
+                     yuv2yuvX_c(c, vLumFilter+dstY*vLumFilterSize,
+                                lumSrcPtr, vLumFilterSize,
+                                vChrFilter+chrDstY*vChrFilterSize,
+                                chrUSrcPtr, chrVSrcPtr, vChrFilterSize,
+                                alpSrcPtr, dest, uDest, vDest, aDest,
 -                               dstW, chrDstW);
++                               dstW, chrDstW, lumDither, chrDither);
+                 }
+             } else {
+                 assert(lumSrcPtr + vLumFilterSize - 1 < lumPixBuf + vLumBufSize*2);
+                 assert(chrUSrcPtr + vChrFilterSize - 1 < chrUPixBuf + vChrBufSize*2);
+                 if(flags & SWS_FULL_CHR_H_INT) {
+                     yuv2rgbX_c_full(c,
+                                     vLumFilter+dstY*vLumFilterSize, lumSrcPtr, vLumFilterSize,
+                                     vChrFilter+dstY*vChrFilterSize, chrUSrcPtr, chrVSrcPtr, vChrFilterSize,
+                                     alpSrcPtr, dest, dstW, dstY);
+                 } else {
+                     yuv2packedX_c(c,
+                                   vLumFilter+dstY*vLumFilterSize, lumSrcPtr, vLumFilterSize,
+                                   vChrFilter+dstY*vChrFilterSize, chrUSrcPtr, chrVSrcPtr, vChrFilterSize,
+                                   alpSrcPtr, dest, dstW, dstY);
+                 }
+             }
+         }
      }
  
-     return 1;
+     if ((dstFormat == PIX_FMT_YUVA420P) && !alpPixBuf)
+         fillPlane(dst[3], dstStride[3], dstW, dstY-lastDstY, lastDstY, 255);
+ #if HAVE_MMX2
+     if (av_get_cpu_flags() & AV_CPU_FLAG_MMX2)
+         __asm__ volatile("sfence":::"memory");
+ #endif
+     emms_c();
+     /* store changed local vars back in the context */
+     c->dstY= dstY;
+     c->lumBufIndex= lumBufIndex;
+     c->chrBufIndex= chrBufIndex;
+     c->lastInLumBuf= lastInLumBuf;
+     c->lastInChrBuf= lastInChrBuf;
+     return dstY - lastDstY;
  }
  
- /**
-  * swscale wrapper, so we don't need to export the SwsContext.
-  * Assumes planar YUV to be in YUV order instead of YVU.
-  */
- int sws_scale(SwsContext *c, const uint8_t* const src[], const int srcStride[], int srcSliceY,
-               int srcSliceH, uint8_t* const dst[], const int dstStride[])
+ static void sws_init_swScale_c(SwsContext *c)
  {
-     int i;
-     const uint8_t* src2[4]= {src[0], src[1], src[2], src[3]};
-     uint8_t* dst2[4]= {dst[0], dst[1], dst[2], dst[3]};
+     enum PixelFormat srcFormat = c->srcFormat;
  
-     // do not mess up sliceDir if we have a "trailing" 0-size slice
-     if (srcSliceH == 0)
-         return 0;
+     c->yuv2nv12X    = yuv2nv12X_c;
+     c->yuv2yuv1     = yuv2yuv1_c;
+     c->yuv2yuvX     = yuv2yuvX_c;
+     c->yuv2packed1  = yuv2packed1_c;
+     c->yuv2packed2  = yuv2packed2_c;
+     c->yuv2packedX  = yuv2packedX_c;
  
-     if (!check_image_pointers(src, c->srcFormat, srcStride)) {
-         av_log(c, AV_LOG_ERROR, "bad src image pointers\n");
-         return 0;
-     }
-     if (!check_image_pointers(dst, c->dstFormat, dstStride)) {
-         av_log(c, AV_LOG_ERROR, "bad dst image pointers\n");
-         return 0;
+     c->hScale       = hScale_c;
+     if (c->flags & SWS_FAST_BILINEAR)
+     {
+         c->hyscale_fast = hyscale_fast_c;
+         c->hcscale_fast = hcscale_fast_c;
      }
  
-     if (c->sliceDir == 0 && srcSliceY != 0 && srcSliceY + srcSliceH != c->srcH) {
-         av_log(c, AV_LOG_ERROR, "Slices start in the middle!\n");
-         return 0;
+     c->chrToYV12 = NULL;
+     switch(srcFormat) {
+         case PIX_FMT_YUYV422  : c->chrToYV12 = yuy2ToUV_c; break;
+         case PIX_FMT_UYVY422  : c->chrToYV12 = uyvyToUV_c; break;
+         case PIX_FMT_NV12     : c->chrToYV12 = nv12ToUV_c; break;
+         case PIX_FMT_NV21     : c->chrToYV12 = nv21ToUV_c; break;
+         case PIX_FMT_RGB8     :
+         case PIX_FMT_BGR8     :
+         case PIX_FMT_PAL8     :
+         case PIX_FMT_BGR4_BYTE:
+         case PIX_FMT_RGB4_BYTE: c->chrToYV12 = palToUV_c; break;
 -        case PIX_FMT_YUV420P9BE: c->chrToYV12 = BE9ToUV_c; break;
 -        case PIX_FMT_YUV420P9LE: c->chrToYV12 = LE9ToUV_c; break;
 -        case PIX_FMT_YUV420P10BE: c->chrToYV12 = BE10ToUV_c; break;
 -        case PIX_FMT_YUV420P10LE: c->chrToYV12 = LE10ToUV_c; break;
++        case PIX_FMT_GRAY16BE :
++        case PIX_FMT_YUV420P9BE:
++        case PIX_FMT_YUV422P10BE:
++        case PIX_FMT_YUV420P10BE:
+         case PIX_FMT_YUV420P16BE:
+         case PIX_FMT_YUV422P16BE:
 -        case PIX_FMT_YUV444P16BE: c->chrToYV12 = BEToUV_c; break;
++        case PIX_FMT_YUV444P16BE: c->hScale16= HAVE_BIGENDIAN ? hScale16_c : hScale16X_c; break;
++        case PIX_FMT_GRAY16LE :
++        case PIX_FMT_YUV420P9LE:
++        case PIX_FMT_YUV422P10LE:
++        case PIX_FMT_YUV420P10LE:
+         case PIX_FMT_YUV420P16LE:
+         case PIX_FMT_YUV422P16LE:
 -        case PIX_FMT_YUV444P16LE: c->chrToYV12 = LEToUV_c; break;
++        case PIX_FMT_YUV444P16LE: c->hScale16= HAVE_BIGENDIAN ? hScale16X_c : hScale16_c; break;
      }
-     if (c->sliceDir == 0) {
-         if (srcSliceY == 0) c->sliceDir = 1; else c->sliceDir = -1;
+     if (c->chrSrcHSubSample) {
+         switch(srcFormat) {
 -        case PIX_FMT_RGB48BE:
 -        case PIX_FMT_RGB48LE: c->chrToYV12 = rgb48ToUV_half_c; break;
 -        case PIX_FMT_BGR48BE:
 -        case PIX_FMT_BGR48LE: c->chrToYV12 = bgr48ToUV_half_c; break;
++        case PIX_FMT_RGB48BE: c->chrToYV12 = rgb48BEToUV_half_c; break;
++        case PIX_FMT_RGB48LE: c->chrToYV12 = rgb48LEToUV_half_c; break;
++        case PIX_FMT_BGR48BE: c->chrToYV12 = bgr48BEToUV_half_c; break;
++        case PIX_FMT_BGR48LE: c->chrToYV12 = bgr48LEToUV_half_c; break;
+         case PIX_FMT_RGB32  : c->chrToYV12 = bgr32ToUV_half_c;  break;
+         case PIX_FMT_RGB32_1: c->chrToYV12 = bgr321ToUV_half_c; break;
+         case PIX_FMT_BGR24  : c->chrToYV12 = bgr24ToUV_half_c; break;
+         case PIX_FMT_BGR565 : c->chrToYV12 = bgr16ToUV_half_c; break;
+         case PIX_FMT_BGR555 : c->chrToYV12 = bgr15ToUV_half_c; break;
+         case PIX_FMT_BGR32  : c->chrToYV12 = rgb32ToUV_half_c;  break;
+         case PIX_FMT_BGR32_1: c->chrToYV12 = rgb321ToUV_half_c; break;
+         case PIX_FMT_RGB24  : c->chrToYV12 = rgb24ToUV_half_c; break;
+         case PIX_FMT_RGB565 : c->chrToYV12 = rgb16ToUV_half_c; break;
+         case PIX_FMT_RGB555 : c->chrToYV12 = rgb15ToUV_half_c; break;
+         }
+     } else {
+         switch(srcFormat) {
 -        case PIX_FMT_RGB48BE:
 -        case PIX_FMT_RGB48LE: c->chrToYV12 = rgb48ToUV_c; break;
 -        case PIX_FMT_BGR48BE:
 -        case PIX_FMT_BGR48LE: c->chrToYV12 = bgr48ToUV_c; break;
++        case PIX_FMT_RGB48BE: c->chrToYV12 = rgb48BEToUV_c; break;
++        case PIX_FMT_RGB48LE: c->chrToYV12 = rgb48LEToUV_c; break;
++        case PIX_FMT_BGR48BE: c->chrToYV12 = bgr48BEToUV_c; break;
++        case PIX_FMT_BGR48LE: c->chrToYV12 = bgr48LEToUV_c; break;
+         case PIX_FMT_RGB32  : c->chrToYV12 = bgr32ToUV_c;  break;
+         case PIX_FMT_RGB32_1: c->chrToYV12 = bgr321ToUV_c; break;
+         case PIX_FMT_BGR24  : c->chrToYV12 = bgr24ToUV_c; break;
+         case PIX_FMT_BGR565 : c->chrToYV12 = bgr16ToUV_c; break;
+         case PIX_FMT_BGR555 : c->chrToYV12 = bgr15ToUV_c; break;
+         case PIX_FMT_BGR32  : c->chrToYV12 = rgb32ToUV_c;  break;
+         case PIX_FMT_BGR32_1: c->chrToYV12 = rgb321ToUV_c; break;
+         case PIX_FMT_RGB24  : c->chrToYV12 = rgb24ToUV_c; break;
+         case PIX_FMT_RGB565 : c->chrToYV12 = rgb16ToUV_c; break;
+         case PIX_FMT_RGB555 : c->chrToYV12 = rgb15ToUV_c; break;
+         }
      }
  
-     if (usePal(c->srcFormat)) {
-         for (i=0; i<256; i++) {
-             int p, r, g, b, y, u, v, a = 0xff;
-             if(c->srcFormat == PIX_FMT_PAL8) {
-                 p=((const uint32_t*)(src[1]))[i];
-                 a= (p>>24)&0xFF;
-                 r= (p>>16)&0xFF;
-                 g= (p>> 8)&0xFF;
-                 b=  p     &0xFF;
-             } else if(c->srcFormat == PIX_FMT_RGB8) {
-                 r= (i>>5    )*36;
-                 g= ((i>>2)&7)*36;
-                 b= (i&3     )*85;
-             } else if(c->srcFormat == PIX_FMT_BGR8) {
-                 b= (i>>6    )*85;
-                 g= ((i>>3)&7)*36;
-                 r= (i&7     )*36;
-             } else if(c->srcFormat == PIX_FMT_RGB4_BYTE) {
-                 r= (i>>3    )*255;
-                 g= ((i>>1)&3)*85;
-                 b= (i&1     )*255;
-             } else if(c->srcFormat == PIX_FMT_GRAY8 || c->srcFormat == PIX_FMT_GRAY8A) {
-                 r = g = b = i;
-             } else {
-                 assert(c->srcFormat == PIX_FMT_BGR4_BYTE);
-                 b= (i>>3    )*255;
-                 g= ((i>>1)&3)*85;
-                 r= (i&1     )*255;
-             }
-             y= av_clip_uint8((RY*r + GY*g + BY*b + ( 33<<(RGB2YUV_SHIFT-1)))>>RGB2YUV_SHIFT);
-             u= av_clip_uint8((RU*r + GU*g + BU*b + (257<<(RGB2YUV_SHIFT-1)))>>RGB2YUV_SHIFT);
-             v= av_clip_uint8((RV*r + GV*g + BV*b + (257<<(RGB2YUV_SHIFT-1)))>>RGB2YUV_SHIFT);
-             c->pal_yuv[i]= y + (u<<8) + (v<<16) + (a<<24);
-             switch(c->dstFormat) {
-             case PIX_FMT_BGR32:
- #if !HAVE_BIGENDIAN
-             case PIX_FMT_RGB24:
- #endif
-                 c->pal_rgb[i]=  r + (g<<8) + (b<<16) + (a<<24);
-                 break;
-             case PIX_FMT_BGR32_1:
- #if HAVE_BIGENDIAN
-             case PIX_FMT_BGR24:
- #endif
-                 c->pal_rgb[i]= a + (r<<8) + (g<<16) + (b<<24);
-                 break;
-             case PIX_FMT_RGB32_1:
- #if HAVE_BIGENDIAN
-             case PIX_FMT_RGB24:
- #endif
-                 c->pal_rgb[i]= a + (b<<8) + (g<<16) + (r<<24);
-                 break;
-             case PIX_FMT_RGB32:
- #if !HAVE_BIGENDIAN
-             case PIX_FMT_BGR24:
- #endif
-             default:
-                 c->pal_rgb[i]=  b + (g<<8) + (r<<16) + (a<<24);
-             }
+     c->lumToYV12 = NULL;
+     c->alpToYV12 = NULL;
+     switch (srcFormat) {
 -    case PIX_FMT_YUV420P9BE: c->lumToYV12 = BE9ToY_c; break;
 -    case PIX_FMT_YUV420P9LE: c->lumToYV12 = LE9ToY_c; break;
 -    case PIX_FMT_YUV420P10BE: c->lumToYV12 = BE10ToY_c; break;
 -    case PIX_FMT_YUV420P10LE: c->lumToYV12 = LE10ToY_c; break;
+     case PIX_FMT_YUYV422  :
 -    case PIX_FMT_YUV420P16BE:
 -    case PIX_FMT_YUV422P16BE:
 -    case PIX_FMT_YUV444P16BE:
 -    case PIX_FMT_Y400A    :
 -    case PIX_FMT_GRAY16BE : c->lumToYV12 = yuy2ToY_c; break;
++    case PIX_FMT_GRAY8A   :
++                            c->lumToYV12 = yuy2ToY_c; break;
+     case PIX_FMT_UYVY422  :
 -    case PIX_FMT_YUV420P16LE:
 -    case PIX_FMT_YUV422P16LE:
 -    case PIX_FMT_YUV444P16LE:
 -    case PIX_FMT_GRAY16LE : c->lumToYV12 = uyvyToY_c; break;
++                            c->lumToYV12 = uyvyToY_c; break;
+     case PIX_FMT_BGR24    : c->lumToYV12 = bgr24ToY_c; break;
+     case PIX_FMT_BGR565   : c->lumToYV12 = bgr16ToY_c; break;
+     case PIX_FMT_BGR555   : c->lumToYV12 = bgr15ToY_c; break;
+     case PIX_FMT_RGB24    : c->lumToYV12 = rgb24ToY_c; break;
+     case PIX_FMT_RGB565   : c->lumToYV12 = rgb16ToY_c; break;
+     case PIX_FMT_RGB555   : c->lumToYV12 = rgb15ToY_c; break;
+     case PIX_FMT_RGB8     :
+     case PIX_FMT_BGR8     :
+     case PIX_FMT_PAL8     :
+     case PIX_FMT_BGR4_BYTE:
+     case PIX_FMT_RGB4_BYTE: c->lumToYV12 = palToY_c; break;
+     case PIX_FMT_MONOBLACK: c->lumToYV12 = monoblack2Y_c; break;
+     case PIX_FMT_MONOWHITE: c->lumToYV12 = monowhite2Y_c; break;
+     case PIX_FMT_RGB32  : c->lumToYV12 = bgr32ToY_c;  break;
+     case PIX_FMT_RGB32_1: c->lumToYV12 = bgr321ToY_c; break;
+     case PIX_FMT_BGR32  : c->lumToYV12 = rgb32ToY_c;  break;
+     case PIX_FMT_BGR32_1: c->lumToYV12 = rgb321ToY_c; break;
 -    case PIX_FMT_RGB48BE:
 -    case PIX_FMT_RGB48LE: c->lumToYV12 = rgb48ToY_c; break;
 -    case PIX_FMT_BGR48BE:
 -    case PIX_FMT_BGR48LE: c->lumToYV12 = bgr48ToY_c; break;
++    case PIX_FMT_RGB48BE: c->lumToYV12 = rgb48BEToY_c; break;
++    case PIX_FMT_RGB48LE: c->lumToYV12 = rgb48LEToY_c; break;
++    case PIX_FMT_BGR48BE: c->lumToYV12 = bgr48BEToY_c; break;
++    case PIX_FMT_BGR48LE: c->lumToYV12 = bgr48LEToY_c; break;
+     }
+     if (c->alpPixBuf) {
+         switch (srcFormat) {
+         case PIX_FMT_RGB32  :
+         case PIX_FMT_RGB32_1:
+         case PIX_FMT_BGR32  :
+         case PIX_FMT_BGR32_1: c->alpToYV12 = abgrToA_c; break;
 -        case PIX_FMT_Y400A  : c->alpToYV12 = yuy2ToY_c; break;
++        case PIX_FMT_GRAY8A : c->alpToYV12 = yuy2ToY_c; break;
++        case PIX_FMT_PAL8   : c->alpToYV12 = palToA_c; break;
          }
      }
  
-     // copy strides, so they can safely be modified
-     if (c->sliceDir == 1) {
-         // slices go from top to bottom
-         int srcStride2[4]= {srcStride[0], srcStride[1], srcStride[2], srcStride[3]};
-         int dstStride2[4]= {dstStride[0], dstStride[1], dstStride[2], dstStride[3]};
-         reset_ptr(src2, c->srcFormat);
-         reset_ptr((const uint8_t**)dst2, c->dstFormat);
++    if(isAnyRGB(c->srcFormat) || c->srcFormat == PIX_FMT_PAL8)
++        c->hScale16= hScale16_c;
 +
-         /* reset slice direction at end of frame */
-         if (srcSliceY + srcSliceH == c->srcH)
-             c->sliceDir = 0;
+     switch (srcFormat) {
 -    case PIX_FMT_Y400A  :
++    case PIX_FMT_GRAY8A :
+         c->alpSrcOffset = 1;
+         break;
+     case PIX_FMT_RGB32  :
+     case PIX_FMT_BGR32  :
+         c->alpSrcOffset = 3;
+         break;
 -    case PIX_FMT_RGB48LE:
 -    case PIX_FMT_BGR48LE:
 -        c->lumSrcOffset = 1;
 -        c->chrSrcOffset = 1;
 -        c->alpSrcOffset = 1;
 -        break;
+     }
  
-         return c->swScale(c, src2, srcStride2, srcSliceY, srcSliceH, dst2, dstStride2);
-     } else {
-         // slices go from bottom to top => we flip the image internally
-         int srcStride2[4]= {-srcStride[0], -srcStride[1], -srcStride[2], -srcStride[3]};
-         int dstStride2[4]= {-dstStride[0], -dstStride[1], -dstStride[2], -dstStride[3]};
-         src2[0] += (srcSliceH-1)*srcStride[0];
-         if (!usePal(c->srcFormat))
-             src2[1] += ((srcSliceH>>c->chrSrcVSubSample)-1)*srcStride[1];
-         src2[2] += ((srcSliceH>>c->chrSrcVSubSample)-1)*srcStride[2];
-         src2[3] += (srcSliceH-1)*srcStride[3];
-         dst2[0] += ( c->dstH                      -1)*dstStride[0];
-         dst2[1] += ((c->dstH>>c->chrDstVSubSample)-1)*dstStride[1];
-         dst2[2] += ((c->dstH>>c->chrDstVSubSample)-1)*dstStride[2];
-         dst2[3] += ( c->dstH                      -1)*dstStride[3];
-         reset_ptr(src2, c->srcFormat);
-         reset_ptr((const uint8_t**)dst2, c->dstFormat);
-         /* reset slice direction at end of frame */
-         if (!srcSliceY)
-             c->sliceDir = 0;
-         return c->swScale(c, src2, srcStride2, c->srcH-srcSliceY-srcSliceH, srcSliceH, dst2, dstStride2);
+     if (c->srcRange != c->dstRange && !isAnyRGB(c->dstFormat)) {
+         if (c->srcRange) {
+             c->lumConvertRange = lumRangeFromJpeg_c;
+             c->chrConvertRange = chrRangeFromJpeg_c;
+         } else {
+             c->lumConvertRange = lumRangeToJpeg_c;
+             c->chrConvertRange = chrRangeToJpeg_c;
+         }
      }
- }
  
- #if LIBSWSCALE_VERSION_MAJOR < 1
- int sws_scale_ordered(SwsContext *c, const uint8_t* const src[], int srcStride[], int srcSliceY,
-                       int srcSliceH, uint8_t* dst[], int dstStride[])
- {
-     return sws_scale(c, src, srcStride, srcSliceY, srcSliceH, dst, dstStride);
+     if (!(isGray(srcFormat) || isGray(c->dstFormat) ||
+           srcFormat == PIX_FMT_MONOBLACK || srcFormat == PIX_FMT_MONOWHITE))
+         c->needs_hcscale = 1;
  }
- #endif
  
- /* Convert the palette to the same packed 32-bit format as the palette */
- void sws_convertPalette8ToPacked32(const uint8_t *src, uint8_t *dst, int num_pixels, const uint8_t *palette)
+ SwsFunc ff_getSwsFunc(SwsContext *c)
  {
-     int i;
+     sws_init_swScale_c(c);
  
-     for (i=0; i<num_pixels; i++)
-         ((uint32_t *) dst)[i] = ((const uint32_t *) palette)[src[i]];
- }
+     if (HAVE_MMX)
+         ff_sws_init_swScale_mmx(c);
+     if (HAVE_ALTIVEC)
+         ff_sws_init_swScale_altivec(c);
  
- /* Palette format: ABCD -> dst format: ABC */
- void sws_convertPalette8ToPacked24(const uint8_t *src, uint8_t *dst, int num_pixels, const uint8_t *palette)
- {
-     int i;
-     for (i=0; i<num_pixels; i++) {
-         //FIXME slow?
-         dst[0]= palette[src[i]*4+0];
-         dst[1]= palette[src[i]*4+1];
-         dst[2]= palette[src[i]*4+2];
-         dst+= 3;
-     }
+     return swScale;
  }
@@@ -35,6 -35,6 +35,8 @@@
  
  #define MAX_FILTER_SIZE 256
  
++#define DITHER1XBPP
++
  #if HAVE_BIGENDIAN
  #define ALT32_CORR (-1)
  #else
@@@ -343,19 -338,8 +348,14 @@@ SwsFunc ff_yuv2rgb_init_mlib(SwsContex
  SwsFunc ff_yuv2rgb_init_altivec(SwsContext *c);
  SwsFunc ff_yuv2rgb_get_func_ptr_bfin(SwsContext *c);
  void ff_bfin_get_unscaled_swscale(SwsContext *c);
- void ff_yuv2packedX_altivec(SwsContext *c, const int16_t *lumFilter,
-                             const int16_t **lumSrc, int lumFilterSize,
-                             const int16_t *chrFilter, const int16_t **chrUSrc,
-                             const int16_t **chrVSrc, int chrFilterSize,
-                             uint8_t *dest, int dstW, int dstY);
  
 +#if FF_API_SWS_FORMAT_NAME
 +/**
 + * @deprecated Use av_get_pix_fmt_name() instead.
 + */
 +attribute_deprecated
  const char *sws_format_name(enum PixelFormat format);
 +#endif
  
  //FIXME replace this with something faster
  #define is16BPS(x)      (           \
          || (x)==PIX_FMT_BGR32_1     \
          || (x)==PIX_FMT_RGB32       \
          || (x)==PIX_FMT_RGB32_1     \
 -        || (x)==PIX_FMT_Y400A       \
 +        || (x)==PIX_FMT_PAL8        \
 +        || (x)==PIX_FMT_GRAY8A      \
          || (x)==PIX_FMT_YUVA420P    \
      )
 -#define usePal(x) ((av_pix_fmt_descriptors[x].flags & PIX_FMT_PAL) || (x) == PIX_FMT_Y400A)
+ #define isPacked(x)         (       \
+            (x)==PIX_FMT_PAL8        \
+         || (x)==PIX_FMT_YUYV422     \
+         || (x)==PIX_FMT_UYVY422     \
+         || (x)==PIX_FMT_Y400A       \
+         || isAnyRGB(x)              \
+     )
 +#define usePal(x) ((av_pix_fmt_descriptors[x].flags & PIX_FMT_PAL) || (x) == PIX_FMT_GRAY8A)
  
  extern const uint64_t ff_dither4[2];
  extern const uint64_t ff_dither8[2];
++extern const uint8_t dithers[8][8][8];
++extern uint16_t dither_scale[15][16];
++
  
  extern const AVClass sws_context_class;
  
index 58e05ac,0000000..9ae9fc7
mode 100644,000000..100644
--- /dev/null
@@@ -1,991 -1,0 +1,748 @@@
- static inline void bgr24ToY_c(int16_t *dst, const uint8_t *src,
-                               int width, uint32_t *unused)
- {
-     int i;
-     for (i=0; i<width; i++) {
-         int b= src[i*3+0];
-         int g= src[i*3+1];
-         int r= src[i*3+2];
-         dst[i]= ((RY*r + GY*g + BY*b + (32<<(RGB2YUV_SHIFT-1)) + (1<<(RGB2YUV_SHIFT-7)))>>(RGB2YUV_SHIFT-6));
-     }
- }
- static inline void bgr24ToUV_c(int16_t *dstU, int16_t *dstV, const uint8_t *src1,
-                                const uint8_t *src2, int width, uint32_t *unused)
- {
-     int i;
-     for (i=0; i<width; i++) {
-         int b= src1[3*i + 0];
-         int g= src1[3*i + 1];
-         int r= src1[3*i + 2];
-         dstU[i]= (RU*r + GU*g + BU*b + (256<<(RGB2YUV_SHIFT-1)) + (1<<(RGB2YUV_SHIFT-7)))>>(RGB2YUV_SHIFT-6);
-         dstV[i]= (RV*r + GV*g + BV*b + (256<<(RGB2YUV_SHIFT-1)) + (1<<(RGB2YUV_SHIFT-7)))>>(RGB2YUV_SHIFT-6);
-     }
-     assert(src1 == src2);
- }
- static inline void bgr24ToUV_half_c(int16_t *dstU, int16_t *dstV, const uint8_t *src1,
-                                     const uint8_t *src2, int width, uint32_t *unused)
- {
-     int i;
-     for (i=0; i<width; i++) {
-         int b= src1[6*i + 0] + src1[6*i + 3];
-         int g= src1[6*i + 1] + src1[6*i + 4];
-         int r= src1[6*i + 2] + src1[6*i + 5];
-         dstU[i]= (RU*r + GU*g + BU*b + (256<<RGB2YUV_SHIFT) + (1<<(RGB2YUV_SHIFT-6)))>>(RGB2YUV_SHIFT-5);
-         dstV[i]= (RV*r + GV*g + BV*b + (256<<RGB2YUV_SHIFT) + (1<<(RGB2YUV_SHIFT-6)))>>(RGB2YUV_SHIFT-5);
-     }
-     assert(src1 == src2);
- }
- static inline void rgb24ToY_c(int16_t *dst, const uint8_t *src, int width,
-                               uint32_t *unused)
- {
-     int i;
-     for (i=0; i<width; i++) {
-         int r= src[i*3+0];
-         int g= src[i*3+1];
-         int b= src[i*3+2];
-         dst[i]= ((RY*r + GY*g + BY*b + (32<<(RGB2YUV_SHIFT-1)) + (1<<(RGB2YUV_SHIFT-7)))>>(RGB2YUV_SHIFT-6));
-     }
- }
- static inline void rgb24ToUV_c(int16_t *dstU, int16_t *dstV, const uint8_t *src1,
-                                const uint8_t *src2, int width, uint32_t *unused)
- {
-     int i;
-     assert(src1==src2);
-     for (i=0; i<width; i++) {
-         int r= src1[3*i + 0];
-         int g= src1[3*i + 1];
-         int b= src1[3*i + 2];
-         dstU[i]= (RU*r + GU*g + BU*b + (256<<(RGB2YUV_SHIFT-1)) + (1<<(RGB2YUV_SHIFT-7)))>>(RGB2YUV_SHIFT-6);
-         dstV[i]= (RV*r + GV*g + BV*b + (256<<(RGB2YUV_SHIFT-1)) + (1<<(RGB2YUV_SHIFT-7)))>>(RGB2YUV_SHIFT-6);
-     }
- }
- static inline void rgb24ToUV_half_c(int16_t *dstU, int16_t *dstV, const uint8_t *src1,
-                                     const uint8_t *src2, int width, uint32_t *unused)
- {
-     int i;
-     assert(src1==src2);
-     for (i=0; i<width; i++) {
-         int r= src1[6*i + 0] + src1[6*i + 3];
-         int g= src1[6*i + 1] + src1[6*i + 4];
-         int b= src1[6*i + 2] + src1[6*i + 5];
-         dstU[i]= (RU*r + GU*g + BU*b + (256<<RGB2YUV_SHIFT) + (1<<(RGB2YUV_SHIFT-6)))>>(RGB2YUV_SHIFT-5);
-         dstV[i]= (RV*r + GV*g + BV*b + (256<<RGB2YUV_SHIFT) + (1<<(RGB2YUV_SHIFT-6)))>>(RGB2YUV_SHIFT-5);
-     }
- }
 +/*
 + * Copyright (C) 2001-2003 Michael Niedermayer <michaelni@gmx.at>
 + *
 + * This file is part of FFmpeg.
 + *
 + * 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.
 + *
 + * 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 FFmpeg; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
 +static inline void yuv2yuvX_c(SwsContext *c, const int16_t *lumFilter,
 +                              const int16_t **lumSrc, int lumFilterSize,
 +                              const int16_t *chrFilter, const int16_t **chrUSrc,
 +                              const int16_t **chrVSrc,
 +                              int chrFilterSize, const int16_t **alpSrc,
 +                              uint8_t *dest, uint8_t *uDest, uint8_t *vDest,
 +                              uint8_t *aDest, int dstW, int chrDstW, const uint8_t *lumDither, const uint8_t *chrDither)
 +{
 +    yuv2yuvXinC(lumFilter, lumSrc, lumFilterSize,
 +                chrFilter, chrUSrc, chrVSrc, chrFilterSize,
 +                alpSrc, dest, uDest, vDest, aDest, dstW, chrDstW, lumDither, chrDither);
 +}
 +
 +static inline void yuv2nv12X_c(SwsContext *c, const int16_t *lumFilter,
 +                               const int16_t **lumSrc, int lumFilterSize,
 +                               const int16_t *chrFilter, const int16_t **chrUSrc,
 +                               const int16_t **chrVSrc,
 +                               int chrFilterSize, uint8_t *dest, uint8_t *uDest,
 +                               int dstW, int chrDstW, enum PixelFormat dstFormat, const uint8_t *dither, const uint8_t *chrDither)
 +{
 +    yuv2nv12XinC(lumFilter, lumSrc, lumFilterSize,
 +                 chrFilter, chrUSrc, chrVSrc, chrFilterSize,
 +                 dest, uDest, dstW, chrDstW, dstFormat, dither, chrDither);
 +}
 +
 +static inline void yuv2yuv1_c(SwsContext *c, const int16_t *lumSrc,
 +                              const int16_t *chrUSrc, const int16_t *chrVSrc,
 +                              const int16_t *alpSrc,
 +                              uint8_t *dest, uint8_t *uDest, uint8_t *vDest,
 +                              uint8_t *aDest, int dstW, int chrDstW, const uint8_t *lumDither, const uint8_t *chrDither)
 +{
 +    int i;
 +
 +    for (i=0; i<dstW; i++) {
 +        int val= (lumSrc[i]+lumDither[i&7])>>7;
 +        dest[i]= av_clip_uint8(val);
 +    }
 +
 +    if (uDest)
 +        for (i=0; i<chrDstW; i++) {
 +            int u=(chrUSrc[i]+chrDither[i&7])>>7;
 +            int v=(chrVSrc[i]+chrDither[(i+3)&7])>>7;
 +            uDest[i]= av_clip_uint8(u);
 +            vDest[i]= av_clip_uint8(v);
 +        }
 +
 +    if (CONFIG_SWSCALE_ALPHA && aDest)
 +        for (i=0; i<dstW; i++) {
 +            int val= (alpSrc[i]+lumDither[i&7])>>7;
 +            aDest[i]= av_clip_uint8(val);
 +        }
 +}
 +
 +
 +/**
 + * vertical scale YV12 to RGB
 + */
 +static inline void yuv2packedX_c(SwsContext *c, const int16_t *lumFilter,
 +                                 const int16_t **lumSrc, int lumFilterSize,
 +                                 const int16_t *chrFilter, const int16_t **chrUSrc,
 +                                 const int16_t **chrVSrc,
 +                                 int chrFilterSize, const int16_t **alpSrc,
 +                                 uint8_t *dest, int dstW, int dstY)
 +{
 +        yuv2packedXinC(c, lumFilter, lumSrc, lumFilterSize,
 +                       chrFilter, chrUSrc, chrVSrc, chrFilterSize,
 +                       alpSrc, dest, dstW, dstY);
 +}
 +
 +/**
 + * vertical bilinear scale YV12 to RGB
 + */
 +static inline void yuv2packed2_c(SwsContext *c, const uint16_t *buf0,
 +                                 const uint16_t *buf1, const uint16_t *ubuf0,
 +                                 const uint16_t *ubuf1, const uint16_t *vbuf0,
 +                                 const uint16_t *vbuf1, const uint16_t *abuf0,
 +                                 const uint16_t *abuf1, uint8_t *dest, int dstW,
 +                                 int yalpha, int uvalpha, int y)
 +{
 +    int  yalpha1=4095- yalpha;
 +    int uvalpha1=4095-uvalpha;
 +    int i;
 +
 +    YSCALE_YUV_2_ANYRGB_C(YSCALE_YUV_2_RGB2_C, YSCALE_YUV_2_PACKED2_C(void,0), YSCALE_YUV_2_GRAY16_2_C, YSCALE_YUV_2_MONO2_C)
 +}
 +
 +/**
 + * YV12 to RGB without scaling or interpolating
 + */
 +static inline void yuv2packed1_c(SwsContext *c, const uint16_t *buf0,
 +                                 const uint16_t *ubuf0, const uint16_t *ubuf1,
 +                                 const uint16_t *vbuf0, const uint16_t *vbuf1,
 +                                 const uint16_t *abuf0, uint8_t *dest, int dstW,
 +                                 int uvalpha, enum PixelFormat dstFormat,
 +                                 int flags, int y)
 +{
 +    const int yalpha1=0;
 +    int i;
 +
 +    const uint16_t *buf1= buf0; //FIXME needed for RGB1/BGR1
 +    const int yalpha= 4096; //FIXME ...
 +
 +    if (uvalpha < 2048) {
 +        YSCALE_YUV_2_ANYRGB_C(YSCALE_YUV_2_RGB1_C, YSCALE_YUV_2_PACKED1_C(void,0), YSCALE_YUV_2_GRAY16_1_C, YSCALE_YUV_2_MONO2_C)
 +    } else {
 +        YSCALE_YUV_2_ANYRGB_C(YSCALE_YUV_2_RGB1B_C, YSCALE_YUV_2_PACKED1B_C(void,0), YSCALE_YUV_2_GRAY16_1_C, YSCALE_YUV_2_MONO2_C)
 +    }
 +}
 +
 +//FIXME yuy2* can read up to 7 samples too much
 +
 +static inline void yuy2ToY_c(uint8_t *dst, const uint8_t *src, int width,
 +                             uint32_t *unused)
 +{
 +    int i;
 +    for (i=0; i<width; i++)
 +        dst[i]= src[2*i];
 +}
 +
 +static inline void yuy2ToUV_c(uint8_t *dstU, uint8_t *dstV, const uint8_t *src1,
 +                              const uint8_t *src2, int width, uint32_t *unused)
 +{
 +    int i;
 +    for (i=0; i<width; i++) {
 +        dstU[i]= src1[4*i + 1];
 +        dstV[i]= src1[4*i + 3];
 +    }
 +    assert(src1 == src2);
 +}
 +
 +static inline void LEToUV_c(uint8_t *dstU, uint8_t *dstV, const uint8_t *src1,
 +                            const uint8_t *src2, int width, uint32_t *unused)
 +{
 +    int i;
 +    // FIXME I don't think this code is right for YUV444/422, since then h is not subsampled so
 +    // we need to skip each second pixel. Same for BEToUV.
 +    for (i=0; i<width; i++) {
 +        dstU[i]= src1[2*i + 1];
 +        dstV[i]= src2[2*i + 1];
 +    }
 +}
 +
 +/* This is almost identical to the previous, end exists only because
 + * yuy2ToY/UV)(dst, src+1, ...) would have 100% unaligned accesses. */
 +static inline void uyvyToY_c(uint8_t *dst, const uint8_t *src, int width,
 +                             uint32_t *unused)
 +{
 +    int i;
 +    for (i=0; i<width; i++)
 +        dst[i]= src[2*i+1];
 +}
 +
 +static inline void uyvyToUV_c(uint8_t *dstU, uint8_t *dstV, const uint8_t *src1,
 +                              const uint8_t *src2, int width, uint32_t *unused)
 +{
 +    int i;
 +    for (i=0; i<width; i++) {
 +        dstU[i]= src1[4*i + 0];
 +        dstV[i]= src1[4*i + 2];
 +    }
 +    assert(src1 == src2);
 +}
 +
 +static inline void BEToUV_c(uint8_t *dstU, uint8_t *dstV, const uint8_t *src1,
 +                            const uint8_t *src2, int width, uint32_t *unused)
 +{
 +    int i;
 +    for (i=0; i<width; i++) {
 +        dstU[i]= src1[2*i];
 +        dstV[i]= src2[2*i];
 +    }
 +}
 +
 +static inline void nvXXtoUV_c(uint8_t *dst1, uint8_t *dst2,
 +                              const uint8_t *src, int width)
 +{
 +    int i;
 +    for (i = 0; i < width; i++) {
 +        dst1[i] = src[2*i+0];
 +        dst2[i] = src[2*i+1];
 +    }
 +}
 +
 +// FIXME Maybe dither instead.
 +#ifndef YUV_NBPS
 +#define YUV_NBPS(depth, endianness, rfunc) \
 +static inline void endianness ## depth ## ToUV_c(uint8_t *dstU, uint8_t *dstV, \
 +                                          const uint16_t *srcU, const uint16_t *srcV, \
 +                                          int width, uint32_t *unused) \
 +{ \
 +    int i; \
 +    for (i = 0; i < width; i++) { \
 +        dstU[i] = rfunc(&srcU[i])>>(depth-8); \
 +        dstV[i] = rfunc(&srcV[i])>>(depth-8); \
 +    } \
 +} \
 +\
 +static inline void endianness ## depth ## ToY_c(uint8_t *dstY, const uint16_t *srcY, int width, uint32_t *unused) \
 +{ \
 +    int i; \
 +    for (i = 0; i < width; i++) \
 +        dstY[i] = rfunc(&srcY[i])>>(depth-8); \
 +} \
 +
 +YUV_NBPS( 9, LE, AV_RL16)
 +YUV_NBPS( 9, BE, AV_RB16)
 +YUV_NBPS(10, LE, AV_RL16)
 +YUV_NBPS(10, BE, AV_RB16)
 +#endif // YUV_NBPS
 +
 +static inline void nv12ToUV_c(uint8_t *dstU, uint8_t *dstV,
 +                              const uint8_t *src1, const uint8_t *src2,
 +                              int width, uint32_t *unused)
 +{
 +    nvXXtoUV_c(dstU, dstV, src1, width);
 +}
 +
 +static inline void nv21ToUV_c(uint8_t *dstU, uint8_t *dstV,
 +                              const uint8_t *src1, const uint8_t *src2,
 +                              int width, uint32_t *unused)
 +{
 +    nvXXtoUV_c(dstV, dstU, src1, width);
 +}
 +
- static inline void hScale16_c(int16_t *dst, int dstW, const uint16_t *src, int srcW, int xInc,
-                                     const int16_t *filter, const int16_t *filterPos, long filterSize, int shift)
- {
-     int i, j;
-     for (i=0; i<dstW; i++) {
-         int srcPos= filterPos[i];
-         int val=0;
-         for (j=0; j<filterSize; j++) {
-             val += ((int)src[srcPos + j])*filter[filterSize*i + j];
-         }
-         dst[i] = FFMIN(val>>shift, (1<<15)-1); // the cubic equation does overflow ...
-     }
- }
- static inline void hScale16X_c(int16_t *dst, int dstW, const uint16_t *src, int srcW, int xInc,
-                                     const int16_t *filter, const int16_t *filterPos, long filterSize, int shift)
- {
-     int i, j;
-     for (i=0; i<dstW; i++) {
-         int srcPos= filterPos[i];
-         int val=0;
-         for (j=0; j<filterSize; j++) {
-             val += ((int)av_bswap16(src[srcPos + j]))*filter[filterSize*i + j];
-         }
-         dst[i] = FFMIN(val>>shift, (1<<15)-1); // the cubic equation does overflow ...
-     }
- }
- //FIXME all pal and rgb srcFormats could do this convertion as well
- //FIXME all scalers more complex than bilinear could do half of this transform
- static void chrRangeToJpeg_c(int16_t *dstU, int16_t *dstV, int width)
- {
-     int i;
-     for (i = 0; i < width; i++) {
-         dstU[i] = (FFMIN(dstU[i],30775)*4663 - 9289992)>>12; //-264
-         dstV[i] = (FFMIN(dstV[i],30775)*4663 - 9289992)>>12; //-264
-     }
- }
- static void chrRangeFromJpeg_c(int16_t *dstU, int16_t *dstV, int width)
- {
-     int i;
-     for (i = 0; i < width; i++) {
-         dstU[i] = (dstU[i]*1799 + 4081085)>>11; //1469
-         dstV[i] = (dstV[i]*1799 + 4081085)>>11; //1469
-     }
- }
- static void lumRangeToJpeg_c(int16_t *dst, int width)
- {
-     int i;
-     for (i = 0; i < width; i++)
-         dst[i] = (FFMIN(dst[i],30189)*19077 - 39057361)>>14;
- }
- static void lumRangeFromJpeg_c(int16_t *dst, int width)
- {
-     int i;
-     for (i = 0; i < width; i++)
-         dst[i] = (dst[i]*14071 + 33561947)>>14;
- }
- static inline void hyscale_fast_c(SwsContext *c, int16_t *dst, int dstWidth,
-                                   const uint8_t *src, int srcW, int xInc)
- {
-     int i;
-     unsigned int xpos=0;
-     for (i=0;i<dstWidth;i++) {
-         register unsigned int xx=xpos>>16;
-         register unsigned int xalpha=(xpos&0xFFFF)>>9;
-         dst[i]= (src[xx]<<7) + (src[xx+1] - src[xx])*xalpha;
-         xpos+=xInc;
-     }
-     for (i=dstWidth-1; (i*xInc)>>16 >=srcW-1; i--)
-         dst[i] = src[srcW-1]*128;
- }
-       // *** horizontal scale Y line to temp buffer
- static inline void hyscale_c(SwsContext *c, uint16_t *dst, int dstWidth,
-                              const uint8_t *src, int srcW, int xInc,
-                              const int16_t *hLumFilter,
-                              const int16_t *hLumFilterPos, int hLumFilterSize,
-                              uint8_t *formatConvBuffer,
-                              uint32_t *pal, int isAlpha)
- {
-     void (*toYV12)(uint8_t *, const uint8_t *, int, uint32_t *) = isAlpha ? c->alpToYV12 : c->lumToYV12;
-     void (*convertRange)(int16_t *, int) = isAlpha ? NULL : c->lumConvertRange;
-     src += isAlpha ? c->alpSrcOffset : c->lumSrcOffset;
-     if (toYV12) {
-         toYV12(formatConvBuffer, src, srcW, pal);
-         src= formatConvBuffer;
-     }
-     if (c->hScale16) {
-         int shift= isAnyRGB(c->srcFormat) || c->srcFormat==PIX_FMT_PAL8 ? 13 : av_pix_fmt_descriptors[c->srcFormat].comp[0].depth_minus1;
-         c->hScale16(dst, dstWidth, (const uint16_t*)src, srcW, xInc, hLumFilter, hLumFilterPos, hLumFilterSize, shift);
-     } else if (!c->hyscale_fast) {
-         c->hScale(dst, dstWidth, src, srcW, xInc, hLumFilter, hLumFilterPos, hLumFilterSize);
-     } else { // fast bilinear upscale / crap downscale
-         c->hyscale_fast(c, dst, dstWidth, src, srcW, xInc);
-     }
-     if (convertRange)
-         convertRange(dst, dstWidth);
- }
- static inline void hcscale_fast_c(SwsContext *c, int16_t *dst1, int16_t *dst2,
-                                   int dstWidth, const uint8_t *src1,
-                                   const uint8_t *src2, int srcW, int xInc)
- {
-     int i;
-     unsigned int xpos=0;
-     for (i=0;i<dstWidth;i++) {
-         register unsigned int xx=xpos>>16;
-         register unsigned int xalpha=(xpos&0xFFFF)>>9;
-         dst1[i]=(src1[xx]*(xalpha^127)+src1[xx+1]*xalpha);
-         dst2[i]=(src2[xx]*(xalpha^127)+src2[xx+1]*xalpha);
-         xpos+=xInc;
-     }
-     for (i=dstWidth-1; (i*xInc)>>16 >=srcW-1; i--) {
-         dst1[i] = src1[srcW-1]*128;
-         dst2[i] = src2[srcW-1]*128;
-     }
- }
- inline static void hcscale_c(SwsContext *c, uint16_t *dst1, uint16_t *dst2, int dstWidth,
-                              const uint8_t *src1, const uint8_t *src2,
-                              int srcW, int xInc, const int16_t *hChrFilter,
-                              const int16_t *hChrFilterPos, int hChrFilterSize,
-                              uint8_t *formatConvBuffer, uint32_t *pal)
- {
-     src1 += c->chrSrcOffset;
-     src2 += c->chrSrcOffset;
-     if (c->chrToYV12) {
-         uint8_t *buf2 = formatConvBuffer + FFALIGN(srcW*2+78, 16);
-         c->chrToYV12(formatConvBuffer, buf2, src1, src2, srcW, pal);
-         src1= formatConvBuffer;
-         src2= buf2;
-     }
-     if (c->hScale16) {
-         int shift= isAnyRGB(c->srcFormat) || c->srcFormat==PIX_FMT_PAL8 ? 13 : av_pix_fmt_descriptors[c->srcFormat].comp[0].depth_minus1;
-         c->hScale16(dst1, dstWidth, (const uint16_t*)src1, srcW, xInc, hChrFilter, hChrFilterPos, hChrFilterSize, shift);
-         c->hScale16(dst2, dstWidth, (const uint16_t*)src2, srcW, xInc, hChrFilter, hChrFilterPos, hChrFilterSize, shift);
-     } else if (!c->hcscale_fast) {
-         c->hScale(dst1, dstWidth, src1, srcW, xInc, hChrFilter, hChrFilterPos, hChrFilterSize);
-         c->hScale(dst2, dstWidth, src2, srcW, xInc, hChrFilter, hChrFilterPos, hChrFilterSize);
-     } else { // fast bilinear upscale / crap downscale
-         c->hcscale_fast(c, dst1, dst2, dstWidth, src1, src2, srcW, xInc);
-     }
-     if (c->chrConvertRange)
-         c->chrConvertRange(dst1, dst2, dstWidth);
- }
 +// bilinear / bicubic scaling
 +static inline void hScale_c(int16_t *dst, int dstW, const uint8_t *src,
 +                            int srcW, int xInc,
 +                            const int16_t *filter, const int16_t *filterPos,
 +                            int filterSize)
 +{
 +    int i;
 +    for (i=0; i<dstW; i++) {
 +        int j;
 +        int srcPos= filterPos[i];
 +        int val=0;
 +        for (j=0; j<filterSize; j++) {
 +            val += ((int)src[srcPos + j])*filter[filterSize*i + j];
 +        }
 +        //filter += hFilterSize;
 +        dst[i] = FFMIN(val>>7, (1<<15)-1); // the cubic equation does overflow ...
 +        //dst[i] = val>>7;
 +    }
 +}
 +
 +
 +#define DEBUG_SWSCALE_BUFFERS 0
 +#define DEBUG_BUFFERS(...) if (DEBUG_SWSCALE_BUFFERS) av_log(c, AV_LOG_DEBUG, __VA_ARGS__)
 +
 +#if HAVE_MMX
 +static void updateMMXDitherTables(SwsContext *c, int dstY, int lumBufIndex, int chrBufIndex,
 +                                  int lastInLumBuf, int lastInChrBuf);
 +#endif
 +
 +static int swScale_c(SwsContext *c, const uint8_t* src[], int srcStride[],
 +                     int srcSliceY, int srcSliceH, uint8_t* dst[], int dstStride[])
 +{
 +    /* load a few things into local vars to make the code more readable? and faster */
 +    const int srcW= c->srcW;
 +    const int dstW= c->dstW;
 +    const int dstH= c->dstH;
 +    const int chrDstW= c->chrDstW;
 +    const int chrSrcW= c->chrSrcW;
 +    const int lumXInc= c->lumXInc;
 +    const int chrXInc= c->chrXInc;
 +    const enum PixelFormat dstFormat= c->dstFormat;
 +    const int flags= c->flags;
 +    int16_t *vLumFilterPos= c->vLumFilterPos;
 +    int16_t *vChrFilterPos= c->vChrFilterPos;
 +    int16_t *hLumFilterPos= c->hLumFilterPos;
 +    int16_t *hChrFilterPos= c->hChrFilterPos;
 +    int16_t *vLumFilter= c->vLumFilter;
 +    int16_t *vChrFilter= c->vChrFilter;
 +    int16_t *hLumFilter= c->hLumFilter;
 +    int16_t *hChrFilter= c->hChrFilter;
 +    int32_t *lumMmxFilter= c->lumMmxFilter;
 +    int32_t *chrMmxFilter= c->chrMmxFilter;
 +    int32_t av_unused *alpMmxFilter= c->alpMmxFilter;
 +    const int vLumFilterSize= c->vLumFilterSize;
 +    const int vChrFilterSize= c->vChrFilterSize;
 +    const int hLumFilterSize= c->hLumFilterSize;
 +    const int hChrFilterSize= c->hChrFilterSize;
 +    int16_t **lumPixBuf= c->lumPixBuf;
 +    int16_t **chrUPixBuf= c->chrUPixBuf;
 +    int16_t **chrVPixBuf= c->chrVPixBuf;
 +    int16_t **alpPixBuf= c->alpPixBuf;
 +    const int vLumBufSize= c->vLumBufSize;
 +    const int vChrBufSize= c->vChrBufSize;
 +    uint8_t *formatConvBuffer= c->formatConvBuffer;
 +    const int chrSrcSliceY= srcSliceY >> c->chrSrcVSubSample;
 +    const int chrSrcSliceH= -((-srcSliceH) >> c->chrSrcVSubSample);
 +    int lastDstY;
 +    uint32_t *pal=c->pal_yuv;
 +
 +    /* vars which will change and which we need to store back in the context */
 +    int dstY= c->dstY;
 +    int lumBufIndex= c->lumBufIndex;
 +    int chrBufIndex= c->chrBufIndex;
 +    int lastInLumBuf= c->lastInLumBuf;
 +    int lastInChrBuf= c->lastInChrBuf;
 +
 +    if (isPacked(c->srcFormat)) {
 +        src[0]=
 +        src[1]=
 +        src[2]=
 +        src[3]= src[0];
 +        srcStride[0]=
 +        srcStride[1]=
 +        srcStride[2]=
 +        srcStride[3]= srcStride[0];
 +    }
 +    srcStride[1]<<= c->vChrDrop;
 +    srcStride[2]<<= c->vChrDrop;
 +
 +    DEBUG_BUFFERS("swScale() %p[%d] %p[%d] %p[%d] %p[%d] -> %p[%d] %p[%d] %p[%d] %p[%d]\n",
 +                  src[0], srcStride[0], src[1], srcStride[1], src[2], srcStride[2], src[3], srcStride[3],
 +                  dst[0], dstStride[0], dst[1], dstStride[1], dst[2], dstStride[2], dst[3], dstStride[3]);
 +    DEBUG_BUFFERS("srcSliceY: %d srcSliceH: %d dstY: %d dstH: %d\n",
 +                   srcSliceY,    srcSliceH,    dstY,    dstH);
 +    DEBUG_BUFFERS("vLumFilterSize: %d vLumBufSize: %d vChrFilterSize: %d vChrBufSize: %d\n",
 +                   vLumFilterSize,    vLumBufSize,    vChrFilterSize,    vChrBufSize);
 +
 +    if (dstStride[0]%8 !=0 || dstStride[1]%8 !=0 || dstStride[2]%8 !=0 || dstStride[3]%8 != 0) {
 +        static int warnedAlready=0; //FIXME move this into the context perhaps
 +        if (flags & SWS_PRINT_INFO && !warnedAlready) {
 +            av_log(c, AV_LOG_WARNING, "Warning: dstStride is not aligned!\n"
 +                   "         ->cannot do aligned memory accesses anymore\n");
 +            warnedAlready=1;
 +        }
 +    }
 +
 +    /* Note the user might start scaling the picture in the middle so this
 +       will not get executed. This is not really intended but works
 +       currently, so people might do it. */
 +    if (srcSliceY ==0) {
 +        lumBufIndex=-1;
 +        chrBufIndex=-1;
 +        dstY=0;
 +        lastInLumBuf= -1;
 +        lastInChrBuf= -1;
 +    }
 +
 +    lastDstY= dstY;
 +
 +    for (;dstY < dstH; dstY++) {
 +        unsigned char *dest =dst[0]+dstStride[0]*dstY;
 +        const int chrDstY= dstY>>c->chrDstVSubSample;
 +        unsigned char *uDest=dst[1]+dstStride[1]*chrDstY;
 +        unsigned char *vDest=dst[2]+dstStride[2]*chrDstY;
 +        unsigned char *aDest=(CONFIG_SWSCALE_ALPHA && alpPixBuf) ? dst[3]+dstStride[3]*dstY : NULL;
 +        const uint8_t *lumDither= isNBPS(c->srcFormat) || is16BPS(c->srcFormat) ? dithers[7][dstY   &7] : flat64;
 +        const uint8_t *chrDither= isNBPS(c->srcFormat) || is16BPS(c->srcFormat) ? dithers[7][chrDstY&7] : flat64;
 +
 +        const int firstLumSrcY= vLumFilterPos[dstY]; //First line needed as input
 +        const int firstLumSrcY2= vLumFilterPos[FFMIN(dstY | ((1<<c->chrDstVSubSample) - 1), dstH-1)];
 +        const int firstChrSrcY= vChrFilterPos[chrDstY]; //First line needed as input
 +        int lastLumSrcY= firstLumSrcY + vLumFilterSize -1; // Last line needed as input
 +        int lastLumSrcY2=firstLumSrcY2+ vLumFilterSize -1; // Last line needed as input
 +        int lastChrSrcY= firstChrSrcY + vChrFilterSize -1; // Last line needed as input
 +        int enough_lines;
 +
 +        //handle holes (FAST_BILINEAR & weird filters)
 +        if (firstLumSrcY > lastInLumBuf) lastInLumBuf= firstLumSrcY-1;
 +        if (firstChrSrcY > lastInChrBuf) lastInChrBuf= firstChrSrcY-1;
 +        assert(firstLumSrcY >= lastInLumBuf - vLumBufSize + 1);
 +        assert(firstChrSrcY >= lastInChrBuf - vChrBufSize + 1);
 +
 +        DEBUG_BUFFERS("dstY: %d\n", dstY);
 +        DEBUG_BUFFERS("\tfirstLumSrcY: %d lastLumSrcY: %d lastInLumBuf: %d\n",
 +                         firstLumSrcY,    lastLumSrcY,    lastInLumBuf);
 +        DEBUG_BUFFERS("\tfirstChrSrcY: %d lastChrSrcY: %d lastInChrBuf: %d\n",
 +                         firstChrSrcY,    lastChrSrcY,    lastInChrBuf);
 +
 +        // Do we have enough lines in this slice to output the dstY line
 +        enough_lines = lastLumSrcY2 < srcSliceY + srcSliceH && lastChrSrcY < -((-srcSliceY - srcSliceH)>>c->chrSrcVSubSample);
 +
 +        if (!enough_lines) {
 +            lastLumSrcY = srcSliceY + srcSliceH - 1;
 +            lastChrSrcY = chrSrcSliceY + chrSrcSliceH - 1;
 +            DEBUG_BUFFERS("buffering slice: lastLumSrcY %d lastChrSrcY %d\n",
 +                                            lastLumSrcY, lastChrSrcY);
 +        }
 +
 +        //Do horizontal scaling
 +        while(lastInLumBuf < lastLumSrcY) {
 +            const uint8_t *src1= src[0]+(lastInLumBuf + 1 - srcSliceY)*srcStride[0];
 +            const uint8_t *src2= src[3]+(lastInLumBuf + 1 - srcSliceY)*srcStride[3];
 +            lumBufIndex++;
 +            assert(lumBufIndex < 2*vLumBufSize);
 +            assert(lastInLumBuf + 1 - srcSliceY < srcSliceH);
 +            assert(lastInLumBuf + 1 - srcSliceY >= 0);
 +            hyscale_c(c, lumPixBuf[ lumBufIndex ], dstW, src1, srcW, lumXInc,
 +                      hLumFilter, hLumFilterPos, hLumFilterSize,
 +                      formatConvBuffer,
 +                      pal, 0);
 +            if (CONFIG_SWSCALE_ALPHA && alpPixBuf)
 +                hyscale_c(c, alpPixBuf[ lumBufIndex ], dstW, src2, srcW,
 +                          lumXInc, hLumFilter, hLumFilterPos, hLumFilterSize,
 +                          formatConvBuffer,
 +                          pal, 1);
 +            lastInLumBuf++;
 +            DEBUG_BUFFERS("\t\tlumBufIndex %d: lastInLumBuf: %d\n",
 +                               lumBufIndex,    lastInLumBuf);
 +        }
 +        while(lastInChrBuf < lastChrSrcY) {
 +            const uint8_t *src1= src[1]+(lastInChrBuf + 1 - chrSrcSliceY)*srcStride[1];
 +            const uint8_t *src2= src[2]+(lastInChrBuf + 1 - chrSrcSliceY)*srcStride[2];
 +            chrBufIndex++;
 +            assert(chrBufIndex < 2*vChrBufSize);
 +            assert(lastInChrBuf + 1 - chrSrcSliceY < (chrSrcSliceH));
 +            assert(lastInChrBuf + 1 - chrSrcSliceY >= 0);
 +            //FIXME replace parameters through context struct (some at least)
 +
 +            if (c->needs_hcscale)
 +                hcscale_c(c, chrUPixBuf[chrBufIndex], chrVPixBuf[chrBufIndex],
 +                          chrDstW, src1, src2, chrSrcW, chrXInc,
 +                          hChrFilter, hChrFilterPos, hChrFilterSize,
 +                          formatConvBuffer, pal);
 +            lastInChrBuf++;
 +            DEBUG_BUFFERS("\t\tchrBufIndex %d: lastInChrBuf: %d\n",
 +                               chrBufIndex,    lastInChrBuf);
 +        }
 +        //wrap buf index around to stay inside the ring buffer
 +        if (lumBufIndex >= vLumBufSize) lumBufIndex-= vLumBufSize;
 +        if (chrBufIndex >= vChrBufSize) chrBufIndex-= vChrBufSize;
 +        if (!enough_lines)
 +            break; //we can't output a dstY line so let's try with the next slice
 +
 +#if HAVE_MMX
 +        updateMMXDitherTables(c, dstY, lumBufIndex, chrBufIndex, lastInLumBuf, lastInChrBuf);
 +#endif
 +        if (dstY < dstH-2) {
 +            const int16_t **lumSrcPtr= (const int16_t **) lumPixBuf + lumBufIndex + firstLumSrcY - lastInLumBuf + vLumBufSize;
 +            const int16_t **chrUSrcPtr= (const int16_t **) chrUPixBuf + chrBufIndex + firstChrSrcY - lastInChrBuf + vChrBufSize;
 +            const int16_t **chrVSrcPtr= (const int16_t **) chrVPixBuf + chrBufIndex + firstChrSrcY - lastInChrBuf + vChrBufSize;
 +            const int16_t **alpSrcPtr= (CONFIG_SWSCALE_ALPHA && alpPixBuf) ? (const int16_t **) alpPixBuf + lumBufIndex + firstLumSrcY - lastInLumBuf + vLumBufSize : NULL;
 +            if (dstFormat == PIX_FMT_NV12 || dstFormat == PIX_FMT_NV21) {
 +                const int chrSkipMask= (1<<c->chrDstVSubSample)-1;
 +                if (dstY&chrSkipMask) uDest= NULL; //FIXME split functions in lumi / chromi
 +                c->yuv2nv12X(c,
 +                             vLumFilter+dstY*vLumFilterSize   , lumSrcPtr, vLumFilterSize,
 +                             vChrFilter+chrDstY*vChrFilterSize, chrUSrcPtr, chrVSrcPtr, vChrFilterSize,
 +                             dest, uDest, dstW, chrDstW, dstFormat, lumDither, chrDither);
 +            } else if (isPlanarYUV(dstFormat) || dstFormat==PIX_FMT_GRAY8) { //YV12 like
 +                const int chrSkipMask= (1<<c->chrDstVSubSample)-1;
 +                if ((dstY&chrSkipMask) || isGray(dstFormat)) uDest=vDest= NULL; //FIXME split functions in lumi / chromi
 +                if (is16BPS(dstFormat) || isNBPS(dstFormat)) {
 +                    yuv2yuvX16inC(vLumFilter+dstY*vLumFilterSize   , lumSrcPtr, vLumFilterSize,
 +                                  vChrFilter+chrDstY*vChrFilterSize, chrUSrcPtr,
 +                                  chrVSrcPtr, vChrFilterSize,
 +                                  alpSrcPtr, (uint16_t *) dest, (uint16_t *) uDest,
 +                                  (uint16_t *) vDest, (uint16_t *) aDest, dstW, chrDstW,
 +                                  dstFormat);
 +                } else if (vLumFilterSize == 1 && vChrFilterSize == 1) { // unscaled YV12
 +                    const int16_t *lumBuf = lumSrcPtr[0];
 +                    const int16_t *chrUBuf= chrUSrcPtr[0];
 +                    const int16_t *chrVBuf= chrVSrcPtr[0];
 +                    const int16_t *alpBuf= (CONFIG_SWSCALE_ALPHA && alpPixBuf) ? alpSrcPtr[0] : NULL;
 +                    c->yuv2yuv1(c, lumBuf, chrUBuf, chrVBuf, alpBuf, dest,
 +                                uDest, vDest, aDest, dstW, chrDstW, lumDither, chrDither);
 +                } else { //General YV12
 +                    c->yuv2yuvX(c,
 +                                vLumFilter+dstY*vLumFilterSize   , lumSrcPtr, vLumFilterSize,
 +                                vChrFilter+chrDstY*vChrFilterSize, chrUSrcPtr,
 +                                chrVSrcPtr, vChrFilterSize,
 +                                alpSrcPtr, dest, uDest, vDest, aDest, dstW, chrDstW, lumDither, chrDither);
 +                }
 +            } else {
 +                assert(lumSrcPtr  + vLumFilterSize - 1 < lumPixBuf  + vLumBufSize*2);
 +                assert(chrUSrcPtr + vChrFilterSize - 1 < chrUPixBuf + vChrBufSize*2);
 +                if (vLumFilterSize == 1 && vChrFilterSize == 2) { //unscaled RGB
 +                    int chrAlpha= vChrFilter[2*dstY+1];
 +                    if(flags & SWS_FULL_CHR_H_INT) {
 +                        yuv2rgbXinC_full(c, //FIXME write a packed1_full function
 +                                         vLumFilter+dstY*vLumFilterSize, lumSrcPtr, vLumFilterSize,
 +                                         vChrFilter+dstY*vChrFilterSize, chrUSrcPtr,
 +                                         chrVSrcPtr, vChrFilterSize,
 +                                         alpSrcPtr, dest, dstW, dstY);
 +                    } else {
 +                        c->yuv2packed1(c, *lumSrcPtr, *chrUSrcPtr, *(chrUSrcPtr+1),
 +                                       *chrVSrcPtr, *(chrVSrcPtr+1),
 +                                       alpPixBuf ? *alpSrcPtr : NULL,
 +                                       dest, dstW, chrAlpha, dstFormat, flags, dstY);
 +                    }
 +                } else if (vLumFilterSize == 2 && vChrFilterSize == 2) { //bilinear upscale RGB
 +                    int lumAlpha= vLumFilter[2*dstY+1];
 +                    int chrAlpha= vChrFilter[2*dstY+1];
 +                    lumMmxFilter[2]=
 +                    lumMmxFilter[3]= vLumFilter[2*dstY   ]*0x10001;
 +                    chrMmxFilter[2]=
 +                    chrMmxFilter[3]= vChrFilter[2*chrDstY]*0x10001;
 +                    if(flags & SWS_FULL_CHR_H_INT) {
 +                        yuv2rgbXinC_full(c, //FIXME write a packed2_full function
 +                                         vLumFilter+dstY*vLumFilterSize, lumSrcPtr, vLumFilterSize,
 +                                         vChrFilter+dstY*vChrFilterSize, chrUSrcPtr, chrVSrcPtr, vChrFilterSize,
 +                                         alpSrcPtr, dest, dstW, dstY);
 +                    } else {
 +                        c->yuv2packed2(c, *lumSrcPtr, *(lumSrcPtr+1), *chrUSrcPtr, *(chrUSrcPtr+1),
 +                                       *chrVSrcPtr, *(chrVSrcPtr+1),
 +                                       alpPixBuf ? *alpSrcPtr : NULL, alpPixBuf ? *(alpSrcPtr+1) : NULL,
 +                                       dest, dstW, lumAlpha, chrAlpha, dstY);
 +                    }
 +                } else { //general RGB
 +                    if(flags & SWS_FULL_CHR_H_INT) {
 +                        yuv2rgbXinC_full(c,
 +                                         vLumFilter+dstY*vLumFilterSize, lumSrcPtr, vLumFilterSize,
 +                                         vChrFilter+dstY*vChrFilterSize, chrUSrcPtr, chrVSrcPtr, vChrFilterSize,
 +                                         alpSrcPtr, dest, dstW, dstY);
 +                    } else {
 +                        c->yuv2packedX(c,
 +                                       vLumFilter+dstY*vLumFilterSize, lumSrcPtr, vLumFilterSize,
 +                                       vChrFilter+dstY*vChrFilterSize, chrUSrcPtr, chrVSrcPtr, vChrFilterSize,
 +                                       alpSrcPtr, dest, dstW, dstY);
 +                    }
 +                }
 +            }
 +        } else { // hmm looks like we can't use MMX here without overwriting this array's tail
 +            const int16_t **lumSrcPtr= (const int16_t **)lumPixBuf + lumBufIndex + firstLumSrcY - lastInLumBuf + vLumBufSize;
 +            const int16_t **chrUSrcPtr= (const int16_t **)chrUPixBuf + chrBufIndex + firstChrSrcY - lastInChrBuf + vChrBufSize;
 +            const int16_t **chrVSrcPtr= (const int16_t **)chrVPixBuf + chrBufIndex + firstChrSrcY - lastInChrBuf + vChrBufSize;
 +            const int16_t **alpSrcPtr= (CONFIG_SWSCALE_ALPHA && alpPixBuf) ? (const int16_t **)alpPixBuf + lumBufIndex + firstLumSrcY - lastInLumBuf + vLumBufSize : NULL;
 +            if (dstFormat == PIX_FMT_NV12 || dstFormat == PIX_FMT_NV21) {
 +                const int chrSkipMask= (1<<c->chrDstVSubSample)-1;
 +                if (dstY&chrSkipMask) uDest= NULL; //FIXME split functions in lumi / chromi
 +                yuv2nv12XinC(
 +                             vLumFilter+dstY*vLumFilterSize   , lumSrcPtr, vLumFilterSize,
 +                             vChrFilter+chrDstY*vChrFilterSize, chrUSrcPtr, chrVSrcPtr, vChrFilterSize,
 +                             dest, uDest, dstW, chrDstW, dstFormat, lumDither, chrDither);
 +            } else if (isPlanarYUV(dstFormat) || dstFormat==PIX_FMT_GRAY8) { //YV12
 +                const int chrSkipMask= (1<<c->chrDstVSubSample)-1;
 +                if ((dstY&chrSkipMask) || isGray(dstFormat)) uDest=vDest= NULL; //FIXME split functions in lumi / chromi
 +                if (is16BPS(dstFormat) || isNBPS(dstFormat)) {
 +                    yuv2yuvX16inC(
 +                                  vLumFilter+dstY*vLumFilterSize   , lumSrcPtr, vLumFilterSize,
 +                                  vChrFilter+chrDstY*vChrFilterSize, chrUSrcPtr, chrVSrcPtr, vChrFilterSize,
 +                                  alpSrcPtr, (uint16_t *) dest, (uint16_t *) uDest, (uint16_t *) vDest, (uint16_t *) aDest, dstW, chrDstW,
 +                                  dstFormat);
 +                } else {
 +                    yuv2yuvXinC(
 +                                vLumFilter+dstY*vLumFilterSize   , lumSrcPtr, vLumFilterSize,
 +                                vChrFilter+chrDstY*vChrFilterSize, chrUSrcPtr, chrVSrcPtr, vChrFilterSize,
 +                                alpSrcPtr, dest, uDest, vDest, aDest, dstW, chrDstW, lumDither, chrDither);
 +                }
 +            } else {
 +                assert(lumSrcPtr + vLumFilterSize - 1 < lumPixBuf + vLumBufSize*2);
 +                assert(chrUSrcPtr + vChrFilterSize - 1 < chrUPixBuf + vChrBufSize*2);
 +                if(flags & SWS_FULL_CHR_H_INT) {
 +                    yuv2rgbXinC_full(c,
 +                                     vLumFilter+dstY*vLumFilterSize, lumSrcPtr, vLumFilterSize,
 +                                     vChrFilter+dstY*vChrFilterSize, chrUSrcPtr, chrVSrcPtr, vChrFilterSize,
 +                                     alpSrcPtr, dest, dstW, dstY);
 +                } else {
 +                    yuv2packedXinC(c,
 +                                   vLumFilter+dstY*vLumFilterSize, lumSrcPtr, vLumFilterSize,
 +                                   vChrFilter+dstY*vChrFilterSize, chrUSrcPtr, chrVSrcPtr, vChrFilterSize,
 +                                   alpSrcPtr, dest, dstW, dstY);
 +                }
 +            }
 +        }
 +    }
 +
 +    if ((dstFormat == PIX_FMT_YUVA420P) && !alpPixBuf)
 +        fillPlane(dst[3], dstStride[3], dstW, dstY-lastDstY, lastDstY, 255);
 +
 +#if HAVE_MMX2
 +    if (av_get_cpu_flags() & AV_CPU_FLAG_MMX2)
 +        __asm__ volatile("sfence":::"memory");
 +#endif
 +    emms_c();
 +
 +    /* store changed local vars back in the context */
 +    c->dstY= dstY;
 +    c->lumBufIndex= lumBufIndex;
 +    c->chrBufIndex= chrBufIndex;
 +    c->lastInLumBuf= lastInLumBuf;
 +    c->lastInChrBuf= lastInChrBuf;
 +
 +    return dstY - lastDstY;
 +}
 +
 +static void sws_init_swScale_c(SwsContext *c)
 +{
 +    enum PixelFormat srcFormat = c->srcFormat;
 +
 +    c->yuv2nv12X    = yuv2nv12X_c;
 +    c->yuv2yuv1     = yuv2yuv1_c;
 +    c->yuv2yuvX     = yuv2yuvX_c;
 +    c->yuv2packed1  = yuv2packed1_c;
 +    c->yuv2packed2  = yuv2packed2_c;
 +    c->yuv2packedX  = yuv2packedX_c;
 +
 +    c->hScale       = hScale_c;
 +
 +    if (c->flags & SWS_FAST_BILINEAR)
 +    {
 +        c->hyscale_fast = hyscale_fast_c;
 +        c->hcscale_fast = hcscale_fast_c;
 +    }
 +
 +    c->chrToYV12 = NULL;
 +    switch(srcFormat) {
 +        case PIX_FMT_YUYV422  : c->chrToYV12 = yuy2ToUV_c; break;
 +        case PIX_FMT_UYVY422  : c->chrToYV12 = uyvyToUV_c; break;
 +        case PIX_FMT_NV12     : c->chrToYV12 = nv12ToUV_c; break;
 +        case PIX_FMT_NV21     : c->chrToYV12 = nv21ToUV_c; break;
 +        case PIX_FMT_RGB8     :
 +        case PIX_FMT_BGR8     :
 +        case PIX_FMT_PAL8     :
 +        case PIX_FMT_BGR4_BYTE:
 +        case PIX_FMT_RGB4_BYTE: c->chrToYV12 = palToUV; break;
 +        case PIX_FMT_GRAY16BE :
 +        case PIX_FMT_YUV420P9BE:
 +        case PIX_FMT_YUV422P10BE:
 +        case PIX_FMT_YUV420P10BE:
 +        case PIX_FMT_YUV420P16BE:
 +        case PIX_FMT_YUV422P16BE:
 +        case PIX_FMT_YUV444P16BE: c->hScale16= HAVE_BIGENDIAN ? hScale16_c : hScale16X_c; break;
 +        case PIX_FMT_GRAY16LE :
 +        case PIX_FMT_YUV420P9LE:
 +        case PIX_FMT_YUV422P10LE:
 +        case PIX_FMT_YUV420P10LE:
 +        case PIX_FMT_YUV420P16LE:
 +        case PIX_FMT_YUV422P16LE:
 +        case PIX_FMT_YUV444P16LE: c->hScale16= HAVE_BIGENDIAN ? hScale16X_c : hScale16_c; break;
 +    }
 +    if (c->chrSrcHSubSample) {
 +        switch(srcFormat) {
 +        case PIX_FMT_RGB48BE: c->chrToYV12 = rgb48BEToUV_half; break;
 +        case PIX_FMT_RGB48LE: c->chrToYV12 = rgb48LEToUV_half; break;
 +        case PIX_FMT_BGR48BE: c->chrToYV12 = bgr48BEToUV_half; break;
 +        case PIX_FMT_BGR48LE: c->chrToYV12 = bgr48LEToUV_half; break;
 +        case PIX_FMT_RGB32  : c->chrToYV12 = bgr32ToUV_half;  break;
 +        case PIX_FMT_RGB32_1: c->chrToYV12 = bgr321ToUV_half; break;
 +        case PIX_FMT_BGR24  : c->chrToYV12 = bgr24ToUV_half_c; break;
 +        case PIX_FMT_BGR565 : c->chrToYV12 = bgr16ToUV_half; break;
 +        case PIX_FMT_BGR555 : c->chrToYV12 = bgr15ToUV_half; break;
 +        case PIX_FMT_BGR32  : c->chrToYV12 = rgb32ToUV_half;  break;
 +        case PIX_FMT_BGR32_1: c->chrToYV12 = rgb321ToUV_half; break;
 +        case PIX_FMT_RGB24  : c->chrToYV12 = rgb24ToUV_half_c; break;
 +        case PIX_FMT_RGB565 : c->chrToYV12 = rgb16ToUV_half; break;
 +        case PIX_FMT_RGB555 : c->chrToYV12 = rgb15ToUV_half; break;
 +        }
 +    } else {
 +        switch(srcFormat) {
 +        case PIX_FMT_RGB48BE: c->chrToYV12 = rgb48BEToUV; break;
 +        case PIX_FMT_RGB48LE: c->chrToYV12 = rgb48LEToUV; break;
 +        case PIX_FMT_BGR48BE: c->chrToYV12 = bgr48BEToUV; break;
 +        case PIX_FMT_BGR48LE: c->chrToYV12 = bgr48LEToUV; break;
 +        case PIX_FMT_RGB32  : c->chrToYV12 = bgr32ToUV;  break;
 +        case PIX_FMT_RGB32_1: c->chrToYV12 = bgr321ToUV; break;
 +        case PIX_FMT_BGR24  : c->chrToYV12 = bgr24ToUV_c; break;
 +        case PIX_FMT_BGR565 : c->chrToYV12 = bgr16ToUV; break;
 +        case PIX_FMT_BGR555 : c->chrToYV12 = bgr15ToUV; break;
 +        case PIX_FMT_BGR32  : c->chrToYV12 = rgb32ToUV;  break;
 +        case PIX_FMT_BGR32_1: c->chrToYV12 = rgb321ToUV; break;
 +        case PIX_FMT_RGB24  : c->chrToYV12 = rgb24ToUV_c; break;
 +        case PIX_FMT_RGB565 : c->chrToYV12 = rgb16ToUV; break;
 +        case PIX_FMT_RGB555 : c->chrToYV12 = rgb15ToUV; break;
 +        }
 +    }
 +
 +    c->lumToYV12 = NULL;
 +    c->alpToYV12 = NULL;
 +    switch (srcFormat) {
 +    case PIX_FMT_YUYV422  :
 +    case PIX_FMT_GRAY8A   :
 +                            c->lumToYV12 = yuy2ToY_c; break;
 +    case PIX_FMT_UYVY422  :
 +                            c->lumToYV12 = uyvyToY_c; break;
 +    case PIX_FMT_BGR24    : c->lumToYV12 = bgr24ToY_c; break;
 +    case PIX_FMT_BGR565   : c->lumToYV12 = bgr16ToY; break;
 +    case PIX_FMT_BGR555   : c->lumToYV12 = bgr15ToY; break;
 +    case PIX_FMT_RGB24    : c->lumToYV12 = rgb24ToY_c; break;
 +    case PIX_FMT_RGB565   : c->lumToYV12 = rgb16ToY; break;
 +    case PIX_FMT_RGB555   : c->lumToYV12 = rgb15ToY; break;
 +    case PIX_FMT_RGB8     :
 +    case PIX_FMT_BGR8     :
 +    case PIX_FMT_PAL8     :
 +    case PIX_FMT_BGR4_BYTE:
 +    case PIX_FMT_RGB4_BYTE: c->lumToYV12 = palToY; break;
 +    case PIX_FMT_MONOBLACK: c->lumToYV12 = monoblack2Y; break;
 +    case PIX_FMT_MONOWHITE: c->lumToYV12 = monowhite2Y; break;
 +    case PIX_FMT_RGB32  : c->lumToYV12 = bgr32ToY;  break;
 +    case PIX_FMT_RGB32_1: c->lumToYV12 = bgr321ToY; break;
 +    case PIX_FMT_BGR32  : c->lumToYV12 = rgb32ToY;  break;
 +    case PIX_FMT_BGR32_1: c->lumToYV12 = rgb321ToY; break;
 +    case PIX_FMT_RGB48BE: c->lumToYV12 = rgb48BEToY; break;
 +    case PIX_FMT_RGB48LE: c->lumToYV12 = rgb48LEToY; break;
 +    case PIX_FMT_BGR48BE: c->lumToYV12 = bgr48BEToY; break;
 +    case PIX_FMT_BGR48LE: c->lumToYV12 = bgr48LEToY; break;
 +    }
 +    if (c->alpPixBuf) {
 +        switch (srcFormat) {
 +        case PIX_FMT_RGB32  :
 +        case PIX_FMT_RGB32_1:
 +        case PIX_FMT_BGR32  :
 +        case PIX_FMT_BGR32_1: c->alpToYV12 = abgrToA; break;
 +        case PIX_FMT_GRAY8A : c->alpToYV12 = yuy2ToY_c; break;
 +        case PIX_FMT_PAL8   : c->alpToYV12 = palToA; break;
 +        }
 +    }
 +
 +    if(isAnyRGB(c->srcFormat) || c->srcFormat == PIX_FMT_PAL8)
 +        c->hScale16= hScale16_c;
 +
 +    switch (srcFormat) {
 +    case PIX_FMT_GRAY8A :
 +        c->alpSrcOffset = 1;
 +        break;
 +    case PIX_FMT_RGB32  :
 +    case PIX_FMT_BGR32  :
 +        c->alpSrcOffset = 3;
 +        break;
 +    }
 +
 +    if (c->srcRange != c->dstRange && !isAnyRGB(c->dstFormat)) {
 +        if (c->srcRange) {
 +            c->lumConvertRange = lumRangeFromJpeg_c;
 +            c->chrConvertRange = chrRangeFromJpeg_c;
 +        } else {
 +            c->lumConvertRange = lumRangeToJpeg_c;
 +            c->chrConvertRange = chrRangeToJpeg_c;
 +        }
 +    }
 +
 +    if (!(isGray(srcFormat) || isGray(c->dstFormat) ||
 +          srcFormat == PIX_FMT_MONOBLACK || srcFormat == PIX_FMT_MONOWHITE))
 +        c->needs_hcscale = 1;
 +}
index 0000000,87cd655..e0c4b25
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,887 +1,849 @@@
 - * This file is part of Libav.
+ /*
+  * Copyright (C) 2001-2003 Michael Niedermayer <michaelni@gmx.at>
+  *
 - * Libav is free software; you can redistribute it and/or
++ * This file is part of FFmpeg.
+  *
 - * Libav is distributed in the hope that it will be useful,
++ * 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.
+  *
 - * License along with Libav; if not, write to the Free Software
++ * 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
 -    if (srcFormat == PIX_FMT_Y400A) {
++ * License along with FFmpeg; if not, write to the Free Software
+  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+  */
+ #include <inttypes.h>
+ #include <string.h>
+ #include <math.h>
+ #include <stdio.h>
+ #include "config.h"
+ #include <assert.h>
+ #include "swscale.h"
+ #include "swscale_internal.h"
+ #include "rgb2rgb.h"
+ #include "libavutil/intreadwrite.h"
+ #include "libavutil/cpu.h"
+ #include "libavutil/avutil.h"
+ #include "libavutil/mathematics.h"
+ #include "libavutil/bswap.h"
+ #include "libavutil/pixdesc.h"
+ #define RGB2YUV_SHIFT 15
+ #define BY ( (int)(0.114*219/255*(1<<RGB2YUV_SHIFT)+0.5))
+ #define BV (-(int)(0.081*224/255*(1<<RGB2YUV_SHIFT)+0.5))
+ #define BU ( (int)(0.500*224/255*(1<<RGB2YUV_SHIFT)+0.5))
+ #define GY ( (int)(0.587*219/255*(1<<RGB2YUV_SHIFT)+0.5))
+ #define GV (-(int)(0.419*224/255*(1<<RGB2YUV_SHIFT)+0.5))
+ #define GU (-(int)(0.331*224/255*(1<<RGB2YUV_SHIFT)+0.5))
+ #define RY ( (int)(0.299*219/255*(1<<RGB2YUV_SHIFT)+0.5))
+ #define RV ( (int)(0.500*224/255*(1<<RGB2YUV_SHIFT)+0.5))
+ #define RU (-(int)(0.169*224/255*(1<<RGB2YUV_SHIFT)+0.5))
+ static void fillPlane(uint8_t* plane, int stride, int width, int height, int y, uint8_t val)
+ {
+     int i;
+     uint8_t *ptr = plane + stride*y;
+     for (i=0; i<height; i++) {
+         memset(ptr, val, width);
+         ptr += stride;
+     }
+ }
+ static void copyPlane(const uint8_t *src, int srcStride,
+                       int srcSliceY, int srcSliceH, int width,
+                       uint8_t *dst, int dstStride)
+ {
+     dst += dstStride * srcSliceY;
+     if (dstStride == srcStride && srcStride > 0) {
+         memcpy(dst, src, srcSliceH * dstStride);
+     } else {
+         int i;
+         for (i=0; i<srcSliceH; i++) {
+             memcpy(dst, src, width);
+             src += srcStride;
+             dst += dstStride;
+         }
+     }
+ }
+ static int planarToNv12Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
+                                int srcSliceH, uint8_t* dstParam[], int dstStride[])
+ {
+     uint8_t *dst = dstParam[1] + dstStride[1]*srcSliceY/2;
+     copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW,
+               dstParam[0], dstStride[0]);
+     if (c->dstFormat == PIX_FMT_NV12)
+         interleaveBytes(src[1], src[2], dst, c->srcW/2, srcSliceH/2, srcStride[1], srcStride[2], dstStride[0]);
+     else
+         interleaveBytes(src[2], src[1], dst, c->srcW/2, srcSliceH/2, srcStride[2], srcStride[1], dstStride[0]);
+     return srcSliceH;
+ }
+ static int planarToYuy2Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
+                                int srcSliceH, uint8_t* dstParam[], int dstStride[])
+ {
+     uint8_t *dst=dstParam[0] + dstStride[0]*srcSliceY;
+     yv12toyuy2(src[0], src[1], src[2], dst, c->srcW, srcSliceH, srcStride[0], srcStride[1], dstStride[0]);
+     return srcSliceH;
+ }
+ static int planarToUyvyWrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
+                                int srcSliceH, uint8_t* dstParam[], int dstStride[])
+ {
+     uint8_t *dst=dstParam[0] + dstStride[0]*srcSliceY;
+     yv12touyvy(src[0], src[1], src[2], dst, c->srcW, srcSliceH, srcStride[0], srcStride[1], dstStride[0]);
+     return srcSliceH;
+ }
+ static int yuv422pToYuy2Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
+                                 int srcSliceH, uint8_t* dstParam[], int dstStride[])
+ {
+     uint8_t *dst=dstParam[0] + dstStride[0]*srcSliceY;
+     yuv422ptoyuy2(src[0],src[1],src[2],dst,c->srcW,srcSliceH,srcStride[0],srcStride[1],dstStride[0]);
+     return srcSliceH;
+ }
+ static int yuv422pToUyvyWrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
+                                 int srcSliceH, uint8_t* dstParam[], int dstStride[])
+ {
+     uint8_t *dst=dstParam[0] + dstStride[0]*srcSliceY;
+     yuv422ptouyvy(src[0],src[1],src[2],dst,c->srcW,srcSliceH,srcStride[0],srcStride[1],dstStride[0]);
+     return srcSliceH;
+ }
+ static int yuyvToYuv420Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
+                                int srcSliceH, uint8_t* dstParam[], int dstStride[])
+ {
+     uint8_t *ydst=dstParam[0] + dstStride[0]*srcSliceY;
+     uint8_t *udst=dstParam[1] + dstStride[1]*srcSliceY/2;
+     uint8_t *vdst=dstParam[2] + dstStride[2]*srcSliceY/2;
+     yuyvtoyuv420(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0], dstStride[1], srcStride[0]);
+     if (dstParam[3])
+         fillPlane(dstParam[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255);
+     return srcSliceH;
+ }
+ static int yuyvToYuv422Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
+                                int srcSliceH, uint8_t* dstParam[], int dstStride[])
+ {
+     uint8_t *ydst=dstParam[0] + dstStride[0]*srcSliceY;
+     uint8_t *udst=dstParam[1] + dstStride[1]*srcSliceY;
+     uint8_t *vdst=dstParam[2] + dstStride[2]*srcSliceY;
+     yuyvtoyuv422(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0], dstStride[1], srcStride[0]);
+     return srcSliceH;
+ }
+ static int uyvyToYuv420Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
+                                int srcSliceH, uint8_t* dstParam[], int dstStride[])
+ {
+     uint8_t *ydst=dstParam[0] + dstStride[0]*srcSliceY;
+     uint8_t *udst=dstParam[1] + dstStride[1]*srcSliceY/2;
+     uint8_t *vdst=dstParam[2] + dstStride[2]*srcSliceY/2;
+     uyvytoyuv420(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0], dstStride[1], srcStride[0]);
+     if (dstParam[3])
+         fillPlane(dstParam[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255);
+     return srcSliceH;
+ }
+ static int uyvyToYuv422Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
+                                int srcSliceH, uint8_t* dstParam[], int dstStride[])
+ {
+     uint8_t *ydst=dstParam[0] + dstStride[0]*srcSliceY;
+     uint8_t *udst=dstParam[1] + dstStride[1]*srcSliceY;
+     uint8_t *vdst=dstParam[2] + dstStride[2]*srcSliceY;
+     uyvytoyuv422(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0], dstStride[1], srcStride[0]);
+     return srcSliceH;
+ }
+ static void gray8aToPacked32(const uint8_t *src, uint8_t *dst, int num_pixels, const uint8_t *palette)
+ {
+     int i;
+     for (i=0; i<num_pixels; i++)
+         ((uint32_t *) dst)[i] = ((const uint32_t *)palette)[src[i<<1]] | (src[(i<<1)+1] << 24);
+ }
+ static void gray8aToPacked32_1(const uint8_t *src, uint8_t *dst, int num_pixels, const uint8_t *palette)
+ {
+     int i;
+     for (i=0; i<num_pixels; i++)
+         ((uint32_t *) dst)[i] = ((const uint32_t *)palette)[src[i<<1]] | src[(i<<1)+1];
+ }
+ static void gray8aToPacked24(const uint8_t *src, uint8_t *dst, int num_pixels, const uint8_t *palette)
+ {
+     int i;
+     for (i=0; i<num_pixels; i++) {
+         //FIXME slow?
+         dst[0]= palette[src[i<<1]*4+0];
+         dst[1]= palette[src[i<<1]*4+1];
+         dst[2]= palette[src[i<<1]*4+2];
+         dst+= 3;
+     }
+ }
+ static int palToRgbWrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
+                            int srcSliceH, uint8_t* dst[], int dstStride[])
+ {
+     const enum PixelFormat srcFormat= c->srcFormat;
+     const enum PixelFormat dstFormat= c->dstFormat;
+     void (*conv)(const uint8_t *src, uint8_t *dst, int num_pixels,
+                  const uint8_t *palette)=NULL;
+     int i;
+     uint8_t *dstPtr= dst[0] + dstStride[0]*srcSliceY;
+     const uint8_t *srcPtr= src[0];
 -               sws_format_name(srcFormat), sws_format_name(dstFormat));
++    if (srcFormat == PIX_FMT_GRAY8A) {
+         switch (dstFormat) {
+         case PIX_FMT_RGB32  : conv = gray8aToPacked32; break;
+         case PIX_FMT_BGR32  : conv = gray8aToPacked32; break;
+         case PIX_FMT_BGR32_1: conv = gray8aToPacked32_1; break;
+         case PIX_FMT_RGB32_1: conv = gray8aToPacked32_1; break;
+         case PIX_FMT_RGB24  : conv = gray8aToPacked24; break;
+         case PIX_FMT_BGR24  : conv = gray8aToPacked24; break;
+         }
+     } else if (usePal(srcFormat)) {
+         switch (dstFormat) {
+         case PIX_FMT_RGB32  : conv = sws_convertPalette8ToPacked32; break;
+         case PIX_FMT_BGR32  : conv = sws_convertPalette8ToPacked32; break;
+         case PIX_FMT_BGR32_1: conv = sws_convertPalette8ToPacked32; break;
+         case PIX_FMT_RGB32_1: conv = sws_convertPalette8ToPacked32; break;
+         case PIX_FMT_RGB24  : conv = sws_convertPalette8ToPacked24; break;
+         case PIX_FMT_BGR24  : conv = sws_convertPalette8ToPacked24; break;
+         }
+     }
+     if (!conv)
+         av_log(c, AV_LOG_ERROR, "internal error %s -> %s converter\n",
 -               sws_format_name(srcFormat), sws_format_name(dstFormat));
++               av_get_pix_fmt_name(srcFormat), av_get_pix_fmt_name(dstFormat));
+     else {
+         for (i=0; i<srcSliceH; i++) {
+             conv(srcPtr, dstPtr, c->srcW, (uint8_t *) c->pal_rgb);
+             srcPtr+= srcStride[0];
+             dstPtr+= dstStride[0];
+         }
+     }
+     return srcSliceH;
+ }
+ #define isRGBA32(x) (            \
+            (x) == PIX_FMT_ARGB   \
+         || (x) == PIX_FMT_RGBA   \
+         || (x) == PIX_FMT_BGRA   \
+         || (x) == PIX_FMT_ABGR   \
+         )
+ /* {RGB,BGR}{15,16,24,32,32_1} -> {RGB,BGR}{15,16,24,32} */
+ static int rgbToRgbWrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
+                            int srcSliceH, uint8_t* dst[], int dstStride[])
+ {
+     const enum PixelFormat srcFormat= c->srcFormat;
+     const enum PixelFormat dstFormat= c->dstFormat;
+     const int srcBpp= (c->srcFormatBpp + 7) >> 3;
+     const int dstBpp= (c->dstFormatBpp + 7) >> 3;
+     const int srcId= c->srcFormatBpp >> 2; /* 1:0, 4:1, 8:2, 15:3, 16:4, 24:6, 32:8 */
+     const int dstId= c->dstFormatBpp >> 2;
+     void (*conv)(const uint8_t *src, uint8_t *dst, int src_size)=NULL;
+ #define CONV_IS(src, dst) (srcFormat == PIX_FMT_##src && dstFormat == PIX_FMT_##dst)
+     if (isRGBA32(srcFormat) && isRGBA32(dstFormat)) {
+         if (     CONV_IS(ABGR, RGBA)
+               || CONV_IS(ARGB, BGRA)
+               || CONV_IS(BGRA, ARGB)
+               || CONV_IS(RGBA, ABGR)) conv = shuffle_bytes_3210;
+         else if (CONV_IS(ABGR, ARGB)
+               || CONV_IS(ARGB, ABGR)) conv = shuffle_bytes_0321;
+         else if (CONV_IS(ABGR, BGRA)
+               || CONV_IS(ARGB, RGBA)) conv = shuffle_bytes_1230;
+         else if (CONV_IS(BGRA, RGBA)
+               || CONV_IS(RGBA, BGRA)) conv = shuffle_bytes_2103;
+         else if (CONV_IS(BGRA, ABGR)
+               || CONV_IS(RGBA, ARGB)) conv = shuffle_bytes_3012;
+     } else
+     /* BGR -> BGR */
+     if (  (isBGRinInt(srcFormat) && isBGRinInt(dstFormat))
+        || (isRGBinInt(srcFormat) && isRGBinInt(dstFormat))) {
+         switch(srcId | (dstId<<4)) {
+         case 0x34: conv= rgb16to15; break;
+         case 0x36: conv= rgb24to15; break;
+         case 0x38: conv= rgb32to15; break;
+         case 0x43: conv= rgb15to16; break;
+         case 0x46: conv= rgb24to16; break;
+         case 0x48: conv= rgb32to16; break;
+         case 0x63: conv= rgb15to24; break;
+         case 0x64: conv= rgb16to24; break;
+         case 0x68: conv= rgb32to24; break;
+         case 0x83: conv= rgb15to32; break;
+         case 0x84: conv= rgb16to32; break;
+         case 0x86: conv= rgb24to32; break;
+         }
+     } else if (  (isBGRinInt(srcFormat) && isRGBinInt(dstFormat))
+              || (isRGBinInt(srcFormat) && isBGRinInt(dstFormat))) {
+         switch(srcId | (dstId<<4)) {
+         case 0x33: conv= rgb15tobgr15; break;
+         case 0x34: conv= rgb16tobgr15; break;
+         case 0x36: conv= rgb24tobgr15; break;
+         case 0x38: conv= rgb32tobgr15; break;
+         case 0x43: conv= rgb15tobgr16; break;
+         case 0x44: conv= rgb16tobgr16; break;
+         case 0x46: conv= rgb24tobgr16; break;
+         case 0x48: conv= rgb32tobgr16; break;
+         case 0x63: conv= rgb15tobgr24; break;
+         case 0x64: conv= rgb16tobgr24; break;
+         case 0x66: conv= rgb24tobgr24; break;
+         case 0x68: conv= rgb32tobgr24; break;
+         case 0x83: conv= rgb15tobgr32; break;
+         case 0x84: conv= rgb16tobgr32; break;
+         case 0x86: conv= rgb24tobgr32; break;
+         }
+     }
+     if (!conv) {
+         av_log(c, AV_LOG_ERROR, "internal error %s -> %s converter\n",
 -        if (dstStride[0]*srcBpp == srcStride[0]*dstBpp && srcStride[0] > 0)
++               av_get_pix_fmt_name(srcFormat), av_get_pix_fmt_name(dstFormat));
+     } else {
+         const uint8_t *srcPtr= src[0];
+               uint8_t *dstPtr= dst[0];
+         if ((srcFormat == PIX_FMT_RGB32_1 || srcFormat == PIX_FMT_BGR32_1) && !isRGBA32(dstFormat))
+             srcPtr += ALT32_CORR;
+         if ((dstFormat == PIX_FMT_RGB32_1 || dstFormat == PIX_FMT_BGR32_1) && !isRGBA32(srcFormat))
+             dstPtr += ALT32_CORR;
 -            if(is9_OR_10BPS(c->srcFormat)) {
++        if (dstStride[0]*srcBpp == srcStride[0]*dstBpp && srcStride[0] > 0 && !(srcStride[0]%srcBpp))
+             conv(srcPtr, dstPtr + dstStride[0]*srcSliceY, srcSliceH*srcStride[0]);
+         else {
+             int i;
+             dstPtr += dstStride[0]*srcSliceY;
+             for (i=0; i<srcSliceH; i++) {
+                 conv(srcPtr, dstPtr, c->srcW*srcBpp);
+                 srcPtr+= srcStride[0];
+                 dstPtr+= dstStride[0];
+             }
+         }
+     }
+     return srcSliceH;
+ }
+ static int bgr24ToYv12Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
+                               int srcSliceH, uint8_t* dst[], int dstStride[])
+ {
+     rgb24toyv12(
+         src[0],
+         dst[0]+ srcSliceY    *dstStride[0],
+         dst[1]+(srcSliceY>>1)*dstStride[1],
+         dst[2]+(srcSliceY>>1)*dstStride[2],
+         c->srcW, srcSliceH,
+         dstStride[0], dstStride[1], srcStride[0]);
+     if (dst[3])
+         fillPlane(dst[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255);
+     return srcSliceH;
+ }
+ static int yvu9ToYv12Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
+                              int srcSliceH, uint8_t* dst[], int dstStride[])
+ {
+     copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW,
+               dst[0], dstStride[0]);
+     planar2x(src[1], dst[1] + dstStride[1]*(srcSliceY >> 1), c->chrSrcW,
+              srcSliceH >> 2, srcStride[1], dstStride[1]);
+     planar2x(src[2], dst[2] + dstStride[2]*(srcSliceY >> 1), c->chrSrcW,
+              srcSliceH >> 2, srcStride[2], dstStride[2]);
+     if (dst[3])
+         fillPlane(dst[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255);
+     return srcSliceH;
+ }
+ /* unscaled copy like stuff (assumes nearly identical formats) */
+ static int packedCopyWrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
+                              int srcSliceH, uint8_t* dst[], int dstStride[])
+ {
+     if (dstStride[0]==srcStride[0] && srcStride[0] > 0)
+         memcpy(dst[0] + dstStride[0]*srcSliceY, src[0], srcSliceH*dstStride[0]);
+     else {
+         int i;
+         const uint8_t *srcPtr= src[0];
+         uint8_t *dstPtr= dst[0] + dstStride[0]*srcSliceY;
+         int length=0;
+         /* universal length finder */
+         while(length+c->srcW <= FFABS(dstStride[0])
+            && length+c->srcW <= FFABS(srcStride[0])) length+= c->srcW;
+         assert(length!=0);
+         for (i=0; i<srcSliceH; i++) {
+             memcpy(dstPtr, srcPtr, length);
+             srcPtr+= srcStride[0];
+             dstPtr+= dstStride[0];
+         }
+     }
+     return srcSliceH;
+ }
++#define DITHER_COPY(dst, dstStride, src, srcStride, bswap, dbswap)\
++    uint16_t scale= dither_scale[dst_depth-1][src_depth-1];\
++    int shift= src_depth-dst_depth + dither_scale[src_depth-2][dst_depth-1];\
++    for (i = 0; i < height; i++) {\
++        const uint8_t *dither= dithers[src_depth-9][i&7];\
++        for (j = 0; j < length-7; j+=8){\
++            dst[j+0] = dbswap((bswap(src[j+0]) + dither[0])*scale>>shift);\
++            dst[j+1] = dbswap((bswap(src[j+1]) + dither[1])*scale>>shift);\
++            dst[j+2] = dbswap((bswap(src[j+2]) + dither[2])*scale>>shift);\
++            dst[j+3] = dbswap((bswap(src[j+3]) + dither[3])*scale>>shift);\
++            dst[j+4] = dbswap((bswap(src[j+4]) + dither[4])*scale>>shift);\
++            dst[j+5] = dbswap((bswap(src[j+5]) + dither[5])*scale>>shift);\
++            dst[j+6] = dbswap((bswap(src[j+6]) + dither[6])*scale>>shift);\
++            dst[j+7] = dbswap((bswap(src[j+7]) + dither[7])*scale>>shift);\
++        }\
++        for (; j < length; j++)\
++            dst[j] = dbswap((bswap(src[j]) + dither[j&7])*scale>>shift);\
++        dst += dstStride;\
++        src += srcStride;\
++    }
++
++
+ static int planarCopyWrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
+                              int srcSliceH, uint8_t* dst[], int dstStride[])
+ {
+     int plane, i, j;
+     for (plane=0; plane<4; plane++) {
+         int length= (plane==0 || plane==3) ? c->srcW  : -((-c->srcW  )>>c->chrDstHSubSample);
+         int y=      (plane==0 || plane==3) ? srcSliceY: -((-srcSliceY)>>c->chrDstVSubSample);
+         int height= (plane==0 || plane==3) ? srcSliceH: -((-srcSliceH)>>c->chrDstVSubSample);
+         const uint8_t *srcPtr= src[plane];
+         uint8_t *dstPtr= dst[plane] + dstStride[plane]*y;
+         if (!dst[plane]) continue;
+         // ignore palette for GRAY8
+         if (plane == 1 && !dst[2]) continue;
+         if (!src[plane] || (plane == 1 && !src[2])) {
+             if(is16BPS(c->dstFormat))
+                 length*=2;
+             fillPlane(dst[plane], dstStride[plane], length, height, y, (plane==3) ? 255 : 128);
+         } else {
 -                if (is16BPS(c->dstFormat)) {
 -                    uint16_t *dstPtr2 = (uint16_t*)dstPtr;
 -#define COPY9_OR_10TO16(rfunc, wfunc) \
 -                    for (i = 0; i < height; i++) { \
 -                        for (j = 0; j < length; j++) { \
 -                            int srcpx = rfunc(&srcPtr2[j]); \
 -                            wfunc(&dstPtr2[j], (srcpx<<(16-src_depth)) | (srcpx>>(2*src_depth-16))); \
 -                        } \
 -                        dstPtr2 += dstStride[plane]/2; \
 -                        srcPtr2 += srcStride[plane]/2; \
 -                    }
 -                    if (isBE(c->dstFormat)) {
 -                        if (isBE(c->srcFormat)) {
 -                            COPY9_OR_10TO16(AV_RB16, AV_WB16);
 -                        } else {
 -                            COPY9_OR_10TO16(AV_RL16, AV_WB16);
 -                        }
++            if(isNBPS(c->srcFormat) || isNBPS(c->dstFormat)
++               || (is16BPS(c->srcFormat) != is16BPS(c->dstFormat))
++            ) {
+                 const int src_depth = av_pix_fmt_descriptors[c->srcFormat].comp[plane].depth_minus1+1;
+                 const int dst_depth = av_pix_fmt_descriptors[c->dstFormat].comp[plane].depth_minus1+1;
+                 const uint16_t *srcPtr2 = (const uint16_t*)srcPtr;
++                uint16_t *dstPtr2 = (uint16_t*)dstPtr;
 -                        if (isBE(c->srcFormat)) {
 -                            COPY9_OR_10TO16(AV_RB16, AV_WL16);
 -                        } else {
 -                            COPY9_OR_10TO16(AV_RL16, AV_WL16);
 -                        }
 -                    }
 -                } else if (is9_OR_10BPS(c->dstFormat)) {
 -                    uint16_t *dstPtr2 = (uint16_t*)dstPtr;
 -#define COPY9_OR_10TO9_OR_10(loop) \
 -                    for (i = 0; i < height; i++) { \
 -                        for (j = 0; j < length; j++) { \
 -                            loop; \
 -                        } \
 -                        dstPtr2 += dstStride[plane]/2; \
 -                        srcPtr2 += srcStride[plane]/2; \
++                if (dst_depth == 8) {
++                    if(isBE(c->srcFormat) == HAVE_BIGENDIAN){
++                        DITHER_COPY(dstPtr, dstStride[plane], srcPtr2, srcStride[plane]/2, , )
+                     } else {
 -#define COPY9_OR_10TO9_OR_10_2(rfunc, wfunc) \
 -                    if (dst_depth > src_depth) { \
 -                        COPY9_OR_10TO9_OR_10(int srcpx = rfunc(&srcPtr2[j]); \
 -                            wfunc(&dstPtr2[j], (srcpx << 1) | (srcpx >> 9))); \
 -                    } else if (dst_depth < src_depth) { \
 -                        COPY9_OR_10TO9_OR_10(wfunc(&dstPtr2[j], rfunc(&srcPtr2[j]) >> 1)); \
 -                    } else { \
 -                        COPY9_OR_10TO9_OR_10(wfunc(&dstPtr2[j], rfunc(&srcPtr2[j]))); \
 -                    }
 -                    if (isBE(c->dstFormat)) {
 -                        if (isBE(c->srcFormat)) {
 -                            COPY9_OR_10TO9_OR_10_2(AV_RB16, AV_WB16);
++                        DITHER_COPY(dstPtr, dstStride[plane], srcPtr2, srcStride[plane]/2, av_bswap16, )
+                     }
 -                            COPY9_OR_10TO9_OR_10_2(AV_RL16, AV_WB16);
++                } else if (src_depth == 8) {
++                    for (i = 0; i < height; i++) {
++                        if(isBE(c->dstFormat)){
++                            for (j = 0; j < length; j++)
++                                AV_WB16(&dstPtr2[j], (srcPtr[j]<<(dst_depth-8)) |
++                                                     (srcPtr[j]>>(2*8-dst_depth)));
+                         } else {
 -                    } else {
 -                        if (isBE(c->srcFormat)) {
 -                            COPY9_OR_10TO9_OR_10_2(AV_RB16, AV_WL16);
++                            for (j = 0; j < length; j++)
++                                AV_WL16(&dstPtr2[j], (srcPtr[j]<<(dst_depth-8)) |
++                                                     (srcPtr[j]>>(2*8-dst_depth)));
+                         }
 -                            COPY9_OR_10TO9_OR_10_2(AV_RL16, AV_WL16);
++                        dstPtr2 += dstStride[plane]/2;
++                        srcPtr  += srcStride[plane];
++                    }
++                } else if (src_depth <= dst_depth) {
++                    for (i = 0; i < height; i++) {
++#define COPY_UP(r,w) \
++    for (j = 0; j < length; j++){ \
++        unsigned int v= r(&srcPtr2[j]);\
++        w(&dstPtr2[j], (v<<(dst_depth-src_depth)) | \
++                       (v>>(2*src_depth-dst_depth)));\
++    }
++                        if(isBE(c->srcFormat)){
++                            if(isBE(c->dstFormat)){
++                                COPY_UP(AV_RB16, AV_WB16)
++                            } else {
++                                COPY_UP(AV_RB16, AV_WL16)
++                            }
+                         } else {
 -                    // FIXME Maybe dither instead.
 -#define COPY9_OR_10TO8(rfunc) \
 -                    for (i = 0; i < height; i++) { \
 -                        for (j = 0; j < length; j++) { \
 -                            dstPtr[j] = rfunc(&srcPtr2[j])>>(src_depth-8); \
 -                        } \
 -                        dstPtr  += dstStride[plane]; \
 -                        srcPtr2 += srcStride[plane]/2; \
 -                    }
 -                    if (isBE(c->srcFormat)) {
 -                        COPY9_OR_10TO8(AV_RB16);
 -                    } else {
 -                        COPY9_OR_10TO8(AV_RL16);
 -                    }
 -                }
 -            } else if(is9_OR_10BPS(c->dstFormat)) {
 -                const int dst_depth = av_pix_fmt_descriptors[c->dstFormat].comp[plane].depth_minus1+1;
 -                uint16_t *dstPtr2 = (uint16_t*)dstPtr;
 -
 -                if (is16BPS(c->srcFormat)) {
 -                    const uint16_t *srcPtr2 = (const uint16_t*)srcPtr;
 -#define COPY16TO9_OR_10(rfunc, wfunc) \
 -                    for (i = 0; i < height; i++) { \
 -                        for (j = 0; j < length; j++) { \
 -                            wfunc(&dstPtr2[j], rfunc(&srcPtr2[j])>>(16-dst_depth)); \
 -                        } \
 -                        dstPtr2 += dstStride[plane]/2; \
 -                        srcPtr2 += srcStride[plane]/2; \
 -                    }
 -                    if (isBE(c->dstFormat)) {
 -                        if (isBE(c->srcFormat)) {
 -                            COPY16TO9_OR_10(AV_RB16, AV_WB16);
++                            if(isBE(c->dstFormat)){
++                                COPY_UP(AV_RL16, AV_WB16)
++                            } else {
++                                COPY_UP(AV_RL16, AV_WL16)
++                            }
+                         }
++                        dstPtr2 += dstStride[plane]/2;
++                        srcPtr2 += srcStride[plane]/2;
+                     }
+                 } else {
 -                            COPY16TO9_OR_10(AV_RL16, AV_WB16);
++                    if(isBE(c->srcFormat) == HAVE_BIGENDIAN){
++                        if(isBE(c->dstFormat) == HAVE_BIGENDIAN){
++                            DITHER_COPY(dstPtr2, dstStride[plane]/2, srcPtr2, srcStride[plane]/2, , )
+                         } else {
 -                    } else {
 -                        if (isBE(c->srcFormat)) {
 -                            COPY16TO9_OR_10(AV_RB16, AV_WL16);
++                            DITHER_COPY(dstPtr2, dstStride[plane]/2, srcPtr2, srcStride[plane]/2, , av_bswap16)
+                         }
 -                            COPY16TO9_OR_10(AV_RL16, AV_WL16);
++                    }else{
++                        if(isBE(c->dstFormat) == HAVE_BIGENDIAN){
++                            DITHER_COPY(dstPtr2, dstStride[plane]/2, srcPtr2, srcStride[plane]/2, av_bswap16, )
+                         } else {
 -                } else /* 8bit */ {
 -#define COPY8TO9_OR_10(wfunc) \
 -                    for (i = 0; i < height; i++) { \
 -                        for (j = 0; j < length; j++) { \
 -                            const int srcpx = srcPtr[j]; \
 -                            wfunc(&dstPtr2[j], (srcpx<<(dst_depth-8)) | (srcpx >> (16-dst_depth))); \
 -                        } \
 -                        dstPtr2 += dstStride[plane]/2; \
 -                        srcPtr  += srcStride[plane]; \
 -                    }
 -                    if (isBE(c->dstFormat)) {
 -                        COPY8TO9_OR_10(AV_WB16);
 -                    } else {
 -                        COPY8TO9_OR_10(AV_WL16);
 -                    }
 -                }
 -            } else if(is16BPS(c->srcFormat) && !is16BPS(c->dstFormat)) {
 -                if (!isBE(c->srcFormat)) srcPtr++;
 -                for (i=0; i<height; i++) {
 -                    for (j=0; j<length; j++) dstPtr[j] = srcPtr[j<<1];
 -                    srcPtr+= srcStride[plane];
 -                    dstPtr+= dstStride[plane];
 -                }
 -            } else if(!is16BPS(c->srcFormat) && is16BPS(c->dstFormat)) {
 -                for (i=0; i<height; i++) {
 -                    for (j=0; j<length; j++) {
 -                        dstPtr[ j<<1   ] = srcPtr[j];
 -                        dstPtr[(j<<1)+1] = srcPtr[j];
 -                    }
 -                    srcPtr+= srcStride[plane];
 -                    dstPtr+= dstStride[plane];
++                            DITHER_COPY(dstPtr2, dstStride[plane]/2, srcPtr2, srcStride[plane]/2, av_bswap16, av_bswap16)
+                         }
+                     }
 -            int p, r, g, b,y,u,v;
+                 }
+             } else if(is16BPS(c->srcFormat) && is16BPS(c->dstFormat)
+                   && isBE(c->srcFormat) != isBE(c->dstFormat)) {
+                 for (i=0; i<height; i++) {
+                     for (j=0; j<length; j++)
+                         ((uint16_t*)dstPtr)[j] = av_bswap16(((const uint16_t*)srcPtr)[j]);
+                     srcPtr+= srcStride[plane];
+                     dstPtr+= dstStride[plane];
+                 }
+             } else if (dstStride[plane] == srcStride[plane] &&
+                        srcStride[plane] > 0 && srcStride[plane] == length) {
+                 memcpy(dst[plane] + dstStride[plane]*y, src[plane],
+                        height*dstStride[plane]);
+             } else {
+                 if(is16BPS(c->srcFormat) && is16BPS(c->dstFormat))
+                     length*=2;
+                 for (i=0; i<height; i++) {
+                     memcpy(dstPtr, srcPtr, length);
+                     srcPtr+= srcStride[plane];
+                     dstPtr+= dstStride[plane];
+                 }
+             }
+         }
+     }
+     return srcSliceH;
+ }
+ void ff_get_unscaled_swscale(SwsContext *c)
+ {
+     const enum PixelFormat srcFormat = c->srcFormat;
+     const enum PixelFormat dstFormat = c->dstFormat;
+     const int flags = c->flags;
+     const int dstH = c->dstH;
+     int needsDither;
+     needsDither= isAnyRGB(dstFormat)
+         &&  c->dstFormatBpp < 24
+         && (c->dstFormatBpp < c->srcFormatBpp || (!isAnyRGB(srcFormat)));
+     /* yv12_to_nv12 */
+     if ((srcFormat == PIX_FMT_YUV420P || srcFormat == PIX_FMT_YUVA420P) && (dstFormat == PIX_FMT_NV12 || dstFormat == PIX_FMT_NV21)) {
+         c->swScale= planarToNv12Wrapper;
+     }
+     /* yuv2bgr */
+     if ((srcFormat==PIX_FMT_YUV420P || srcFormat==PIX_FMT_YUV422P || srcFormat==PIX_FMT_YUVA420P) && isAnyRGB(dstFormat)
+         && !(flags & SWS_ACCURATE_RND) && !(dstH&1)) {
+         c->swScale= ff_yuv2rgb_get_func_ptr(c);
+     }
+     if (srcFormat==PIX_FMT_YUV410P && (dstFormat==PIX_FMT_YUV420P || dstFormat==PIX_FMT_YUVA420P) && !(flags & SWS_BITEXACT)) {
+         c->swScale= yvu9ToYv12Wrapper;
+     }
+     /* bgr24toYV12 */
+     if (srcFormat==PIX_FMT_BGR24 && (dstFormat==PIX_FMT_YUV420P || dstFormat==PIX_FMT_YUVA420P) && !(flags & SWS_ACCURATE_RND))
+         c->swScale= bgr24ToYv12Wrapper;
+     /* RGB/BGR -> RGB/BGR (no dither needed forms) */
+     if (   isAnyRGB(srcFormat)
+         && isAnyRGB(dstFormat)
+         && srcFormat != PIX_FMT_BGR8      && dstFormat != PIX_FMT_BGR8
+         && srcFormat != PIX_FMT_RGB8      && dstFormat != PIX_FMT_RGB8
+         && srcFormat != PIX_FMT_BGR4      && dstFormat != PIX_FMT_BGR4
+         && srcFormat != PIX_FMT_RGB4      && dstFormat != PIX_FMT_RGB4
+         && srcFormat != PIX_FMT_BGR4_BYTE && dstFormat != PIX_FMT_BGR4_BYTE
+         && srcFormat != PIX_FMT_RGB4_BYTE && dstFormat != PIX_FMT_RGB4_BYTE
+         && srcFormat != PIX_FMT_MONOBLACK && dstFormat != PIX_FMT_MONOBLACK
+         && srcFormat != PIX_FMT_MONOWHITE && dstFormat != PIX_FMT_MONOWHITE
+         && srcFormat != PIX_FMT_RGB48LE   && dstFormat != PIX_FMT_RGB48LE
+         && srcFormat != PIX_FMT_RGB48BE   && dstFormat != PIX_FMT_RGB48BE
+         && srcFormat != PIX_FMT_BGR48LE   && dstFormat != PIX_FMT_BGR48LE
+         && srcFormat != PIX_FMT_BGR48BE   && dstFormat != PIX_FMT_BGR48BE
+         && (!needsDither || (c->flags&(SWS_FAST_BILINEAR|SWS_POINT))))
+         c->swScale= rgbToRgbWrapper;
+     if ((usePal(srcFormat) && (
+         dstFormat == PIX_FMT_RGB32   ||
+         dstFormat == PIX_FMT_RGB32_1 ||
+         dstFormat == PIX_FMT_RGB24   ||
+         dstFormat == PIX_FMT_BGR32   ||
+         dstFormat == PIX_FMT_BGR32_1 ||
+         dstFormat == PIX_FMT_BGR24)))
+         c->swScale= palToRgbWrapper;
+     if (srcFormat == PIX_FMT_YUV422P) {
+         if (dstFormat == PIX_FMT_YUYV422)
+             c->swScale= yuv422pToYuy2Wrapper;
+         else if (dstFormat == PIX_FMT_UYVY422)
+             c->swScale= yuv422pToUyvyWrapper;
+     }
+     /* LQ converters if -sws 0 or -sws 4*/
+     if (c->flags&(SWS_FAST_BILINEAR|SWS_POINT)) {
+         /* yv12_to_yuy2 */
+         if (srcFormat == PIX_FMT_YUV420P || srcFormat == PIX_FMT_YUVA420P) {
+             if (dstFormat == PIX_FMT_YUYV422)
+                 c->swScale= planarToYuy2Wrapper;
+             else if (dstFormat == PIX_FMT_UYVY422)
+                 c->swScale= planarToUyvyWrapper;
+         }
+     }
+     if(srcFormat == PIX_FMT_YUYV422 && (dstFormat == PIX_FMT_YUV420P || dstFormat == PIX_FMT_YUVA420P))
+         c->swScale= yuyvToYuv420Wrapper;
+     if(srcFormat == PIX_FMT_UYVY422 && (dstFormat == PIX_FMT_YUV420P || dstFormat == PIX_FMT_YUVA420P))
+         c->swScale= uyvyToYuv420Wrapper;
+     if(srcFormat == PIX_FMT_YUYV422 && dstFormat == PIX_FMT_YUV422P)
+         c->swScale= yuyvToYuv422Wrapper;
+     if(srcFormat == PIX_FMT_UYVY422 && dstFormat == PIX_FMT_YUV422P)
+         c->swScale= uyvyToYuv422Wrapper;
+     /* simple copy */
+     if (  srcFormat == dstFormat
+         || (srcFormat == PIX_FMT_YUVA420P && dstFormat == PIX_FMT_YUV420P)
+         || (srcFormat == PIX_FMT_YUV420P && dstFormat == PIX_FMT_YUVA420P)
+         || (isPlanarYUV(srcFormat) && isGray(dstFormat))
+         || (isPlanarYUV(dstFormat) && isGray(srcFormat))
+         || (isGray(dstFormat) && isGray(srcFormat))
+         || (isPlanarYUV(srcFormat) && isPlanarYUV(dstFormat)
+             && c->chrDstHSubSample == c->chrSrcHSubSample
+             && c->chrDstVSubSample == c->chrSrcVSubSample
+             && dstFormat != PIX_FMT_NV12 && dstFormat != PIX_FMT_NV21
+             && srcFormat != PIX_FMT_NV12 && srcFormat != PIX_FMT_NV21))
+     {
+         if (isPacked(c->srcFormat))
+             c->swScale= packedCopyWrapper;
+         else /* Planar YUV or gray */
+             c->swScale= planarCopyWrapper;
+     }
+     if (ARCH_BFIN)
+         ff_bfin_get_unscaled_swscale(c);
+     if (HAVE_ALTIVEC)
+         ff_swscale_get_unscaled_altivec(c);
+ }
+ static void reset_ptr(const uint8_t* src[], int format)
+ {
+     if(!isALPHA(format))
+         src[3]=NULL;
+     if(!isPlanarYUV(format)) {
+         src[3]=src[2]=NULL;
+         if (!usePal(format))
+             src[1]= NULL;
+     }
+ }
+ static int check_image_pointers(uint8_t *data[4], enum PixelFormat pix_fmt,
+                                 const int linesizes[4])
+ {
+     const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[pix_fmt];
+     int i;
+     for (i = 0; i < 4; i++) {
+         int plane = desc->comp[i].plane;
+         if (!data[plane] || !linesizes[plane])
+             return 0;
+     }
+     return 1;
+ }
+ /**
+  * swscale wrapper, so we don't need to export the SwsContext.
+  * Assumes planar YUV to be in YUV order instead of YVU.
+  */
+ int sws_scale(SwsContext *c, const uint8_t* const src[], const int srcStride[], int srcSliceY,
+               int srcSliceH, uint8_t* const dst[], const int dstStride[])
+ {
+     int i;
+     const uint8_t* src2[4]= {src[0], src[1], src[2], src[3]};
+     uint8_t* dst2[4]= {dst[0], dst[1], dst[2], dst[3]};
+     // do not mess up sliceDir if we have a "trailing" 0-size slice
+     if (srcSliceH == 0)
+         return 0;
+     if (!check_image_pointers(src, c->srcFormat, srcStride)) {
+         av_log(c, AV_LOG_ERROR, "bad src image pointers\n");
+         return 0;
+     }
+     if (!check_image_pointers(dst, c->dstFormat, dstStride)) {
+         av_log(c, AV_LOG_ERROR, "bad dst image pointers\n");
+         return 0;
+     }
+     if (c->sliceDir == 0 && srcSliceY != 0 && srcSliceY + srcSliceH != c->srcH) {
+         av_log(c, AV_LOG_ERROR, "Slices start in the middle!\n");
+         return 0;
+     }
+     if (c->sliceDir == 0) {
+         if (srcSliceY == 0) c->sliceDir = 1; else c->sliceDir = -1;
+     }
+     if (usePal(c->srcFormat)) {
+         for (i=0; i<256; i++) {
 -            } else if(c->srcFormat == PIX_FMT_GRAY8 || c->srcFormat == PIX_FMT_Y400A) {
++            int p, r, g, b, y, u, v, a = 0xff;
+             if(c->srcFormat == PIX_FMT_PAL8) {
+                 p=((const uint32_t*)(src[1]))[i];
++                a= (p>>24)&0xFF;
+                 r= (p>>16)&0xFF;
+                 g= (p>> 8)&0xFF;
+                 b=  p     &0xFF;
+             } else if(c->srcFormat == PIX_FMT_RGB8) {
+                 r= (i>>5    )*36;
+                 g= ((i>>2)&7)*36;
+                 b= (i&3     )*85;
+             } else if(c->srcFormat == PIX_FMT_BGR8) {
+                 b= (i>>6    )*85;
+                 g= ((i>>3)&7)*36;
+                 r= (i&7     )*36;
+             } else if(c->srcFormat == PIX_FMT_RGB4_BYTE) {
+                 r= (i>>3    )*255;
+                 g= ((i>>1)&3)*85;
+                 b= (i&1     )*255;
 -            c->pal_yuv[i]= y + (u<<8) + (v<<16);
++            } else if(c->srcFormat == PIX_FMT_GRAY8 || c->srcFormat == PIX_FMT_GRAY8A) {
+                 r = g = b = i;
+             } else {
+                 assert(c->srcFormat == PIX_FMT_BGR4_BYTE);
+                 b= (i>>3    )*255;
+                 g= ((i>>1)&3)*85;
+                 r= (i&1     )*255;
+             }
+             y= av_clip_uint8((RY*r + GY*g + BY*b + ( 33<<(RGB2YUV_SHIFT-1)))>>RGB2YUV_SHIFT);
+             u= av_clip_uint8((RU*r + GU*g + BU*b + (257<<(RGB2YUV_SHIFT-1)))>>RGB2YUV_SHIFT);
+             v= av_clip_uint8((RV*r + GV*g + BV*b + (257<<(RGB2YUV_SHIFT-1)))>>RGB2YUV_SHIFT);
 -                c->pal_rgb[i]=  r + (g<<8) + (b<<16);
++            c->pal_yuv[i]= y + (u<<8) + (v<<16) + (a<<24);
+             switch(c->dstFormat) {
+             case PIX_FMT_BGR32:
+ #if !HAVE_BIGENDIAN
+             case PIX_FMT_RGB24:
+ #endif
 -                c->pal_rgb[i]= (r + (g<<8) + (b<<16)) << 8;
++                c->pal_rgb[i]=  r + (g<<8) + (b<<16) + (a<<24);
+                 break;
+             case PIX_FMT_BGR32_1:
+ #if HAVE_BIGENDIAN
+             case PIX_FMT_BGR24:
+ #endif
 -                c->pal_rgb[i]= (b + (g<<8) + (r<<16)) << 8;
++                c->pal_rgb[i]= a + (r<<8) + (g<<16) + (b<<24);
+                 break;
+             case PIX_FMT_RGB32_1:
+ #if HAVE_BIGENDIAN
+             case PIX_FMT_RGB24:
+ #endif
 -                c->pal_rgb[i]=  b + (g<<8) + (r<<16);
++                c->pal_rgb[i]= a + (b<<8) + (g<<16) + (r<<24);
+                 break;
+             case PIX_FMT_RGB32:
+ #if !HAVE_BIGENDIAN
+             case PIX_FMT_BGR24:
+ #endif
+             default:
++                c->pal_rgb[i]=  b + (g<<8) + (r<<16) + (a<<24);
+             }
+         }
+     }
+     // copy strides, so they can safely be modified
+     if (c->sliceDir == 1) {
+         // slices go from top to bottom
+         int srcStride2[4]= {srcStride[0], srcStride[1], srcStride[2], srcStride[3]};
+         int dstStride2[4]= {dstStride[0], dstStride[1], dstStride[2], dstStride[3]};
+         reset_ptr(src2, c->srcFormat);
+         reset_ptr((const uint8_t**)dst2, c->dstFormat);
+         /* reset slice direction at end of frame */
+         if (srcSliceY + srcSliceH == c->srcH)
+             c->sliceDir = 0;
+         return c->swScale(c, src2, srcStride2, srcSliceY, srcSliceH, dst2, dstStride2);
+     } else {
+         // slices go from bottom to top => we flip the image internally
+         int srcStride2[4]= {-srcStride[0], -srcStride[1], -srcStride[2], -srcStride[3]};
+         int dstStride2[4]= {-dstStride[0], -dstStride[1], -dstStride[2], -dstStride[3]};
+         src2[0] += (srcSliceH-1)*srcStride[0];
+         if (!usePal(c->srcFormat))
+             src2[1] += ((srcSliceH>>c->chrSrcVSubSample)-1)*srcStride[1];
+         src2[2] += ((srcSliceH>>c->chrSrcVSubSample)-1)*srcStride[2];
+         src2[3] += (srcSliceH-1)*srcStride[3];
+         dst2[0] += ( c->dstH                      -1)*dstStride[0];
+         dst2[1] += ((c->dstH>>c->chrDstVSubSample)-1)*dstStride[1];
+         dst2[2] += ((c->dstH>>c->chrDstVSubSample)-1)*dstStride[2];
+         dst2[3] += ( c->dstH                      -1)*dstStride[3];
+         reset_ptr(src2, c->srcFormat);
+         reset_ptr((const uint8_t**)dst2, c->dstFormat);
+         /* reset slice direction at end of frame */
+         if (!srcSliceY)
+             c->sliceDir = 0;
+         return c->swScale(c, src2, srcStride2, c->srcH-srcSliceY-srcSliceH, srcSliceH, dst2, dstStride2);
+     }
+ }
++#if LIBSWSCALE_VERSION_MAJOR < 1
++int sws_scale_ordered(SwsContext *c, const uint8_t* const src[], int srcStride[], int srcSliceY,
++                      int srcSliceH, uint8_t* dst[], int dstStride[])
++{
++    return sws_scale(c, src, srcStride, srcSliceY, srcSliceH, dst, dstStride);
++}
++#endif
++
+ /* Convert the palette to the same packed 32-bit format as the palette */
+ void sws_convertPalette8ToPacked32(const uint8_t *src, uint8_t *dst, int num_pixels, const uint8_t *palette)
+ {
+     int i;
+     for (i=0; i<num_pixels; i++)
+         ((uint32_t *) dst)[i] = ((const uint32_t *) palette)[src[i]];
+ }
+ /* Palette format: ABCD -> dst format: ABC */
+ void sws_convertPalette8ToPacked24(const uint8_t *src, uint8_t *dst, int num_pixels, const uint8_t *palette)
+ {
+     int i;
+     for (i=0; i<num_pixels; i++) {
+         //FIXME slow?
+         dst[0]= palette[src[i]*4+0];
+         dst[1]= palette[src[i]*4+1];
+         dst[2]= palette[src[i]*4+2];
+         dst+= 3;
+     }
+ }
index 0000000,c86f75d..2d5b880
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,187 +1,187 @@@
 - * This file is part of Libav.
+ /*
+  * Copyright (C) 2001-2003 Michael Niedermayer <michaelni@gmx.at>
+  *
 - * Libav is free software; you can redistribute it and/or
++ * This file is part of FFmpeg.
+  *
 - * Libav is distributed in the hope that it will be useful,
++ * 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.
+  *
 - * License along with Libav; if not, write to the Free Software
++ * 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
 -DECLARE_ASM_CONST(8, uint64_t, ff_bgr24toYOffset) = 0x0008400000084000ULL;
++ * License along with FFmpeg; if not, write to the Free Software
+  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+  */
+ #include <inttypes.h>
+ #include "config.h"
+ #include "libswscale/swscale.h"
+ #include "libswscale/swscale_internal.h"
+ #include "libavutil/intreadwrite.h"
+ #include "libavutil/x86_cpu.h"
+ #include "libavutil/cpu.h"
+ #include "libavutil/pixdesc.h"
+ DECLARE_ASM_CONST(8, uint64_t, bF8)=       0xF8F8F8F8F8F8F8F8LL;
+ DECLARE_ASM_CONST(8, uint64_t, bFC)=       0xFCFCFCFCFCFCFCFCLL;
+ DECLARE_ASM_CONST(8, uint64_t, w10)=       0x0010001000100010LL;
+ DECLARE_ASM_CONST(8, uint64_t, w02)=       0x0002000200020002LL;
+ DECLARE_ASM_CONST(8, uint64_t, bm00001111)=0x00000000FFFFFFFFLL;
+ DECLARE_ASM_CONST(8, uint64_t, bm00000111)=0x0000000000FFFFFFLL;
+ DECLARE_ASM_CONST(8, uint64_t, bm11111000)=0xFFFFFFFFFF000000LL;
+ DECLARE_ASM_CONST(8, uint64_t, bm01010101)=0x00FF00FF00FF00FFLL;
+ const DECLARE_ALIGNED(8, uint64_t, ff_dither4)[2] = {
+     0x0103010301030103LL,
+     0x0200020002000200LL,};
+ const DECLARE_ALIGNED(8, uint64_t, ff_dither8)[2] = {
+     0x0602060206020602LL,
+     0x0004000400040004LL,};
+ DECLARE_ASM_CONST(8, uint64_t, b16Mask)=   0x001F001F001F001FLL;
+ DECLARE_ASM_CONST(8, uint64_t, g16Mask)=   0x07E007E007E007E0LL;
+ DECLARE_ASM_CONST(8, uint64_t, r16Mask)=   0xF800F800F800F800LL;
+ DECLARE_ASM_CONST(8, uint64_t, b15Mask)=   0x001F001F001F001FLL;
+ DECLARE_ASM_CONST(8, uint64_t, g15Mask)=   0x03E003E003E003E0LL;
+ DECLARE_ASM_CONST(8, uint64_t, r15Mask)=   0x7C007C007C007C00LL;
+ DECLARE_ALIGNED(8, const uint64_t, ff_M24A)         = 0x00FF0000FF0000FFLL;
+ DECLARE_ALIGNED(8, const uint64_t, ff_M24B)         = 0xFF0000FF0000FF00LL;
+ DECLARE_ALIGNED(8, const uint64_t, ff_M24C)         = 0x0000FF0000FF0000LL;
+ #ifdef FAST_BGR2YV12
+ DECLARE_ALIGNED(8, const uint64_t, ff_bgr2YCoeff)   = 0x000000210041000DULL;
+ DECLARE_ALIGNED(8, const uint64_t, ff_bgr2UCoeff)   = 0x0000FFEEFFDC0038ULL;
+ DECLARE_ALIGNED(8, const uint64_t, ff_bgr2VCoeff)   = 0x00000038FFD2FFF8ULL;
+ #else
+ DECLARE_ALIGNED(8, const uint64_t, ff_bgr2YCoeff)   = 0x000020E540830C8BULL;
+ DECLARE_ALIGNED(8, const uint64_t, ff_bgr2UCoeff)   = 0x0000ED0FDAC23831ULL;
+ DECLARE_ALIGNED(8, const uint64_t, ff_bgr2VCoeff)   = 0x00003831D0E6F6EAULL;
+ #endif /* FAST_BGR2YV12 */
+ DECLARE_ALIGNED(8, const uint64_t, ff_bgr2YOffset)  = 0x1010101010101010ULL;
+ DECLARE_ALIGNED(8, const uint64_t, ff_bgr2UVOffset) = 0x8080808080808080ULL;
+ DECLARE_ALIGNED(8, const uint64_t, ff_w1111)        = 0x0001000100010001ULL;
+ DECLARE_ASM_CONST(8, uint64_t, ff_bgr24toY1Coeff) = 0x0C88000040870C88ULL;
+ DECLARE_ASM_CONST(8, uint64_t, ff_bgr24toY2Coeff) = 0x20DE4087000020DEULL;
+ DECLARE_ASM_CONST(8, uint64_t, ff_rgb24toY1Coeff) = 0x20DE0000408720DEULL;
+ DECLARE_ASM_CONST(8, uint64_t, ff_rgb24toY2Coeff) = 0x0C88408700000C88ULL;
 -DECLARE_ASM_CONST(8, uint64_t, ff_bgr24toUVOffset)= 0x0040400000404000ULL;
++DECLARE_ASM_CONST(8, uint64_t, ff_bgr24toYOffset) = 0x0008010000080100ULL;
+ DECLARE_ASM_CONST(8, uint64_t, ff_bgr24toUV)[2][4] = {
+     {0x38380000DAC83838ULL, 0xECFFDAC80000ECFFULL, 0xF6E40000D0E3F6E4ULL, 0x3838D0E300003838ULL},
+     {0xECFF0000DAC8ECFFULL, 0x3838DAC800003838ULL, 0x38380000D0E33838ULL, 0xF6E4D0E30000F6E4ULL},
+ };
++DECLARE_ASM_CONST(8, uint64_t, ff_bgr24toUVOffset)= 0x0040010000400100ULL;
+ //MMX versions
+ #if HAVE_MMX
+ #undef RENAME
+ #define COMPILE_TEMPLATE_MMX2 0
+ #define RENAME(a) a ## _MMX
+ #include "swscale_template.c"
+ #endif
+ //MMX2 versions
+ #if HAVE_MMX2
+ #undef RENAME
+ #undef COMPILE_TEMPLATE_MMX2
+ #define COMPILE_TEMPLATE_MMX2 1
+ #define RENAME(a) a ## _MMX2
+ #include "swscale_template.c"
+ #endif
+ void updateMMXDitherTables(SwsContext *c, int dstY, int lumBufIndex, int chrBufIndex,
+                            int lastInLumBuf, int lastInChrBuf)
+ {
+     const int dstH= c->dstH;
+     const int flags= c->flags;
+     int16_t **lumPixBuf= c->lumPixBuf;
+     int16_t **chrUPixBuf= c->chrUPixBuf;
+     int16_t **alpPixBuf= c->alpPixBuf;
+     const int vLumBufSize= c->vLumBufSize;
+     const int vChrBufSize= c->vChrBufSize;
+     int16_t *vLumFilterPos= c->vLumFilterPos;
+     int16_t *vChrFilterPos= c->vChrFilterPos;
+     int16_t *vLumFilter= c->vLumFilter;
+     int16_t *vChrFilter= c->vChrFilter;
+     int32_t *lumMmxFilter= c->lumMmxFilter;
+     int32_t *chrMmxFilter= c->chrMmxFilter;
+     int32_t av_unused *alpMmxFilter= c->alpMmxFilter;
+     const int vLumFilterSize= c->vLumFilterSize;
+     const int vChrFilterSize= c->vChrFilterSize;
+     const int chrDstY= dstY>>c->chrDstVSubSample;
+     const int firstLumSrcY= vLumFilterPos[dstY]; //First line needed as input
+     const int firstChrSrcY= vChrFilterPos[chrDstY]; //First line needed as input
+     c->blueDither= ff_dither8[dstY&1];
+     if (c->dstFormat == PIX_FMT_RGB555 || c->dstFormat == PIX_FMT_BGR555)
+         c->greenDither= ff_dither8[dstY&1];
+     else
+         c->greenDither= ff_dither4[dstY&1];
+     c->redDither= ff_dither8[(dstY+1)&1];
+     if (dstY < dstH - 2) {
+         const int16_t **lumSrcPtr= (const int16_t **) lumPixBuf + lumBufIndex + firstLumSrcY - lastInLumBuf + vLumBufSize;
+         const int16_t **chrUSrcPtr= (const int16_t **) chrUPixBuf + chrBufIndex + firstChrSrcY - lastInChrBuf + vChrBufSize;
+         const int16_t **alpSrcPtr= (CONFIG_SWSCALE_ALPHA && alpPixBuf) ? (const int16_t **) alpPixBuf + lumBufIndex + firstLumSrcY - lastInLumBuf + vLumBufSize : NULL;
+         int i;
+         if (flags & SWS_ACCURATE_RND) {
+             int s= APCK_SIZE / 8;
+             for (i=0; i<vLumFilterSize; i+=2) {
+                 *(const void**)&lumMmxFilter[s*i              ]= lumSrcPtr[i  ];
+                 *(const void**)&lumMmxFilter[s*i+APCK_PTR2/4  ]= lumSrcPtr[i+(vLumFilterSize>1)];
+                 lumMmxFilter[s*i+APCK_COEF/4  ]=
+                 lumMmxFilter[s*i+APCK_COEF/4+1]= vLumFilter[dstY*vLumFilterSize + i    ]
+                 + (vLumFilterSize>1 ? vLumFilter[dstY*vLumFilterSize + i + 1]<<16 : 0);
+                 if (CONFIG_SWSCALE_ALPHA && alpPixBuf) {
+                     *(const void**)&alpMmxFilter[s*i              ]= alpSrcPtr[i  ];
+                     *(const void**)&alpMmxFilter[s*i+APCK_PTR2/4  ]= alpSrcPtr[i+(vLumFilterSize>1)];
+                     alpMmxFilter[s*i+APCK_COEF/4  ]=
+                     alpMmxFilter[s*i+APCK_COEF/4+1]= lumMmxFilter[s*i+APCK_COEF/4  ];
+                 }
+             }
+             for (i=0; i<vChrFilterSize; i+=2) {
+                 *(const void**)&chrMmxFilter[s*i              ]= chrUSrcPtr[i  ];
+                 *(const void**)&chrMmxFilter[s*i+APCK_PTR2/4  ]= chrUSrcPtr[i+(vChrFilterSize>1)];
+                 chrMmxFilter[s*i+APCK_COEF/4  ]=
+                 chrMmxFilter[s*i+APCK_COEF/4+1]= vChrFilter[chrDstY*vChrFilterSize + i    ]
+                 + (vChrFilterSize>1 ? vChrFilter[chrDstY*vChrFilterSize + i + 1]<<16 : 0);
+             }
+         } else {
+             for (i=0; i<vLumFilterSize; i++) {
+                 *(const void**)&lumMmxFilter[4*i+0]= lumSrcPtr[i];
+                 lumMmxFilter[4*i+2]=
+                 lumMmxFilter[4*i+3]=
+                 ((uint16_t)vLumFilter[dstY*vLumFilterSize + i])*0x10001;
+                 if (CONFIG_SWSCALE_ALPHA && alpPixBuf) {
+                     *(const void**)&alpMmxFilter[4*i+0]= alpSrcPtr[i];
+                     alpMmxFilter[4*i+2]=
+                     alpMmxFilter[4*i+3]= lumMmxFilter[4*i+2];
+                 }
+             }
+             for (i=0; i<vChrFilterSize; i++) {
+                 *(const void**)&chrMmxFilter[4*i+0]= chrUSrcPtr[i];
+                 chrMmxFilter[4*i+2]=
+                 chrMmxFilter[4*i+3]=
+                 ((uint16_t)vChrFilter[chrDstY*vChrFilterSize + i])*0x10001;
+             }
+         }
+     }
+ }
+ void ff_sws_init_swScale_mmx(SwsContext *c)
+ {
+     int cpu_flags = av_get_cpu_flags();
+     if (cpu_flags & AV_CPU_FLAG_MMX)
+         sws_init_swScale_MMX(c);
+     if (cpu_flags & AV_CPU_FLAG_MMX2)
+         sws_init_swScale_MMX2(c);
+ }
Simple merge
diff --cc subdir.mak
Simple merge