Merge commit '2d60444331fca1910510038dd3817bea885c2367'
authorMichael Niedermayer <michaelni@gmx.at>
Thu, 17 Jul 2014 21:27:40 +0000 (23:27 +0200)
committerMichael Niedermayer <michaelni@gmx.at>
Thu, 17 Jul 2014 21:27:40 +0000 (23:27 +0200)
* commit '2d60444331fca1910510038dd3817bea885c2367':
  dsputil: Split motion estimation compare bits off into their own context

Conflicts:
configure
libavcodec/Makefile
libavcodec/arm/Makefile
libavcodec/dvenc.c
libavcodec/error_resilience.c
libavcodec/h264.h
libavcodec/h264_slice.c
libavcodec/me_cmp.c
libavcodec/me_cmp.h
libavcodec/motion_est.c
libavcodec/motion_est_template.c
libavcodec/mpeg4videoenc.c
libavcodec/mpegvideo.c
libavcodec/mpegvideo_enc.c
libavcodec/x86/Makefile
libavcodec/x86/me_cmp_init.c

Merged-by: Michael Niedermayer <michaelni@gmx.at>
51 files changed:
1  2 
configure
libavcodec/Makefile
libavcodec/ac3enc.c
libavcodec/ac3enc.h
libavcodec/arm/Makefile
libavcodec/arm/me_cmp_armv6.S
libavcodec/arm/me_cmp_init_arm.c
libavcodec/dirac_dwt.c
libavcodec/diracdsp.c
libavcodec/dv.h
libavcodec/dvd_nav_parser.c
libavcodec/dvenc.c
libavcodec/error_resilience.c
libavcodec/error_resilience.h
libavcodec/h264.c
libavcodec/h264.h
libavcodec/h264_slice.c
libavcodec/libavcodec.v
libavcodec/me_cmp.c
libavcodec/me_cmp.h
libavcodec/motion-test.c
libavcodec/motion_est.c
libavcodec/motion_est_template.c
libavcodec/mpeg4videoenc.c
libavcodec/mpegvideo.c
libavcodec/mpegvideo.h
libavcodec/mpegvideo_enc.c
libavcodec/mpegvideoencdsp.c
libavcodec/ppc/Makefile
libavcodec/ppc/me_cmp.c
libavcodec/proresdec.h
libavcodec/proresdec2.c
libavcodec/proresdsp.h
libavcodec/proresenc_anatoliy.c
libavcodec/snow.c
libavcodec/snow.h
libavcodec/snow_dwt.c
libavcodec/snowdec.c
libavcodec/snowenc.c
libavcodec/svq1enc.c
libavcodec/svq1enc.h
libavcodec/utils.c
libavcodec/x86/Makefile
libavcodec/x86/me_cmp.asm
libavcodec/x86/me_cmp_init.c
libavfilter/deshake.h
libavfilter/f_select.c
libavfilter/libmpcodecs/vf_fspp.c
libavfilter/vf_deshake.c
libavfilter/vf_mpdecimate.c
libavfilter/vf_spp.c

diff --cc configure
+++ b/configure
@@@ -1804,11 -1533,8 +1804,10 @@@ CONFIG_EXTRA=
      blockdsp
      bswapdsp
      cabac
-     dsputil
      dvprofile
 +    exif
      fdctdsp
 +    frame_thread_encoder
      gcrypt
      golomb
      gplv3
      idctdsp
      intrax8
      lgplv3
 +    llauddsp
 +    llviddsp
      lpc
+     me_cmp
      mpeg_er
      mpegaudio
      mpegaudiodsp
@@@ -2002,9 -1707,7 +2002,8 @@@ threads_if_any="$THREADS_LIST
  
  # subsystems
  dct_select="rdft"
- dsputil_select="fdctdsp idctdsp pixblockdsp"
- error_resilience_select="dsputil"
+ error_resilience_select="me_cmp"
 +frame_thread_encoder_deps="encoders threads"
  intrax8_select="error_resilience"
  mdct_select="fft"
  rdft_select="fft"
@@@ -2011,17 -1715,16 +2011,17 @@@ me_cmp_select="fdctdsp idctdsp pixblock
  mpeg_er_select="error_resilience"
  mpegaudio_select="mpegaudiodsp"
  mpegaudiodsp_select="dct"
- mpegvideo_select="blockdsp dsputil h264chroma hpeldsp idctdsp videodsp"
- mpegvideoenc_select="dsputil mpegvideo pixblockdsp qpeldsp"
 -mpegvideo_select="blockdsp hpeldsp idctdsp me_cmp videodsp"
++mpegvideo_select="blockdsp h264chroma hpeldsp idctdsp me_cmp videodsp"
+ mpegvideoenc_select="me_cmp mpegvideo pixblockdsp qpeldsp"
  
  # decoders / encoders
  aac_decoder_select="mdct sinewin"
  aac_encoder_select="audio_frame_queue mdct sinewin"
  aac_latm_decoder_select="aac_decoder aac_latm_parser"
  ac3_decoder_select="ac3_parser ac3dsp bswapdsp mdct"
- ac3_encoder_select="ac3dsp audiodsp dsputil mdct"
- ac3_fixed_encoder_select="ac3dsp audiodsp dsputil mdct"
 +ac3_fixed_decoder_select="ac3_parser ac3dsp bswapdsp mdct"
+ ac3_encoder_select="ac3dsp audiodsp mdct me_cmp"
+ ac3_fixed_encoder_select="ac3dsp audiodsp mdct me_cmp"
  aic_decoder_select="golomb idctdsp"
  alac_encoder_select="lpc"
  als_decoder_select="bswapdsp"
@@@ -2048,12 -1749,11 +2048,12 @@@ cook_decoder_select="audiodsp mdct sine
  cscd_decoder_select="lzo"
  cscd_decoder_suggest="zlib"
  dca_decoder_select="mdct"
- dirac_decoder_select="dsputil dwt golomb videodsp mpegvideoenc"
++dirac_decoder_select="dwt golomb videodsp mpegvideoenc"
  dnxhd_decoder_select="blockdsp idctdsp"
  dnxhd_encoder_select="aandcttables blockdsp fdctdsp idctdsp mpegvideoenc pixblockdsp"
  dvvideo_decoder_select="dvprofile idctdsp"
- dvvideo_encoder_select="dsputil dvprofile fdctdsp pixblockdsp"
+ dvvideo_encoder_select="dvprofile fdctdsp me_cmp pixblockdsp"
 -dxa_decoder_deps="zlib"
 +dxa_decoder_select="zlib"
  eac3_decoder_select="ac3_decoder"
  eac3_encoder_select="ac3_encoder"
  eamad_decoder_select="aandcttables blockdsp bswapdsp idctdsp mpegvideo"
@@@ -2144,11 -1844,8 +2144,11 @@@ prores_decoder_select="blockdsp idctdsp
  prores_encoder_select="fdctdsp"
  qcelp_decoder_select="lsp"
  qdm2_decoder_select="mdct rdft mpegaudiodsp"
 -ra_144_encoder_select="audio_frame_queue lpc"
 +ra_144_encoder_select="audio_frame_queue lpc audiodsp"
 +ra_144_decoder_select="audiodsp"
  ralf_decoder_select="golomb"
- rawvideo_decoder_select="dsputil bswapdsp"
- rtjpeg_decoder_select="dsputil"
++rawvideo_decoder_select="bswapdsp"
++rtjpeg_decoder_select="me_cmp"
  rv10_decoder_select="error_resilience h263_decoder h263dsp mpeg_er"
  rv10_encoder_select="h263_encoder"
  rv20_decoder_select="error_resilience h263_decoder h263dsp mpeg_er"
@@@ -2157,14 -1854,9 +2157,14 @@@ rv30_decoder_select="error_resilience g
  rv40_decoder_select="error_resilience golomb h264chroma h264pred h264qpel mpeg_er mpegvideo videodsp"
  shorten_decoder_select="golomb"
  sipr_decoder_select="lsp"
- snow_decoder_select="dsputil dwt h264qpel hpeldsp rangecoder"
- snow_encoder_select="aandcttables dsputil dwt h264qpel hpeldsp mpegvideoenc rangecoder"
++snow_decoder_select="dwt h264qpel hpeldsp rangecoder"
++snow_encoder_select="aandcttables dwt h264qpel hpeldsp me_cmp mpegvideoenc rangecoder"
 +sonic_decoder_select="golomb rangecoder"
 +sonic_encoder_select="golomb rangecoder"
 +sonic_ls_encoder_select="golomb rangecoder"
  sp5x_decoder_select="mjpeg_decoder"
  svq1_decoder_select="hpeldsp"
- svq1_encoder_select="aandcttables dsputil hpeldsp mpegvideoenc"
+ svq1_encoder_select="aandcttables hpeldsp me_cmp mpegvideoenc"
  svq3_decoder_select="h264_decoder hpeldsp tpeldsp"
  svq3_decoder_suggest="zlib"
  tak_decoder_select="audiodsp"
@@@ -2511,76 -2116,25 +2511,76 @@@ azmq_filter_deps="libzmq
  blackframe_filter_deps="gpl"
  boxblur_filter_deps="gpl"
  bs2b_filter_deps="libbs2b"
 +colormatrix_filter_deps="gpl"
  cropdetect_filter_deps="gpl"
 +dctdnoiz_filter_deps="avcodec"
 +dctdnoiz_filter_select="dct"
  delogo_filter_deps="gpl"
- deshake_filter_select="dsputil"
 +deshake_filter_deps="avcodec"
++deshake_filter_select="me_cmp"
  drawtext_filter_deps="libfreetype"
 +ebur128_filter_deps="gpl"
 +flite_filter_deps="libflite"
  frei0r_filter_deps="frei0r dlopen"
  frei0r_filter_extralibs='$ldl'
  frei0r_src_filter_deps="frei0r dlopen"
  frei0r_src_filter_extralibs='$ldl'
 +geq_filter_deps="gpl"
 +histeq_filter_deps="gpl"
  hqdn3d_filter_deps="gpl"
  interlace_filter_deps="gpl"
- mpdecimate_filter_select="dsputil pixblockdsp"
 +kerndeint_filter_deps="gpl"
 +ladspa_filter_deps="ladspa dlopen"
 +ladspa_filter_extralibs='$ldl'
 +mcdeint_filter_deps="avcodec gpl"
 +movie_filter_deps="avcodec avformat"
 +mp_filter_deps="gpl avcodec swscale inline_asm"
 +mpdecimate_filter_deps="gpl avcodec"
++mpdecimate_filter_select="me_cmp pixblockdsp"
 +mptestsrc_filter_deps="gpl"
 +negate_filter_deps="lut_filter"
 +perspective_filter_deps="gpl"
  ocv_filter_deps="libopencv"
 +owdenoise_filter_deps="gpl"
 +pan_filter_deps="swresample"
 +phase_filter_deps="gpl"
 +pp_filter_deps="gpl postproc"
 +pullup_filter_deps="gpl"
 +removelogo_filter_deps="avcodec avformat swscale"
  resample_filter_deps="avresample"
 +sab_filter_deps="gpl swscale"
  scale_filter_deps="swscale"
- spp_filter_select="dsputil fft idctdsp fdctdsp pixblockdsp"
 +smartblur_filter_deps="gpl swscale"
 +showspectrum_filter_deps="avcodec"
 +showspectrum_filter_select="rdft"
 +spp_filter_deps="gpl avcodec"
++spp_filter_select="fft idctdsp fdctdsp me_cmp pixblockdsp"
 +stereo3d_filter_deps="gpl"
 +subtitles_filter_deps="avformat avcodec libass"
 +super2xsai_filter_deps="gpl"
 +tinterlace_filter_deps="gpl"
 +vidstabdetect_filter_deps="libvidstab"
 +vidstabtransform_filter_deps="libvidstab"
 +pixfmts_super2xsai_test_deps="super2xsai_filter"
 +tinterlace_merge_test_deps="tinterlace_filter"
 +tinterlace_pad_test_deps="tinterlace_filter"
 +zmq_filter_deps="libzmq"
 +zoompan_filter_deps="swscale"
  
  # examples
 +avio_reading="avformat avcodec avutil"
  avcodec_example_deps="avcodec avutil"
 +demuxing_decoding_example_deps="avcodec avformat avutil"
  filter_audio_example_deps="avfilter avutil"
 +filtering_audio_example_deps="avfilter avcodec avformat avutil"
 +filtering_video_example_deps="avfilter avcodec avformat avutil"
  metadata_example_deps="avformat avutil"
 -output_example_deps="avcodec avformat avutil swscale"
 -transcode_aac_example_deps="avcodec avformat avresample"
 +muxing_example_deps="avcodec avformat avutil swscale"
 +remuxing_example_deps="avcodec avformat avutil"
 +resampling_audio_example_deps="avutil swresample"
 +scaling_video_example_deps="avutil swscale"
 +transcode_aac_example_deps="avcodec avformat swresample"
 +transcoding_example_deps="avfilter avcodec avformat avutil"
  
  # libraries, in linking order
  avcodec_deps="avutil"
@@@ -39,12 -34,9 +39,11 @@@ OBJS-$(CONFIG_AUDIODSP)                
  OBJS-$(CONFIG_BLOCKDSP)                += blockdsp.o
  OBJS-$(CONFIG_BSWAPDSP)                += bswapdsp.o
  OBJS-$(CONFIG_CABAC)                   += cabac.o
 +OBJS-$(CONFIG_CRYSTALHD)               += crystalhd.o
  OBJS-$(CONFIG_DCT)                     += dct.o dct32_fixed.o dct32_float.o
- OBJS-$(CONFIG_DSPUTIL)                 += dsputil.o
  OBJS-$(CONFIG_DXVA2)                   += dxva2.o
  OBJS-$(CONFIG_ERROR_RESILIENCE)        += error_resilience.o
 +OBJS-$(CONFIG_EXIF)                    += exif.o tiff_common.o
  OBJS-$(CONFIG_FDCTDSP)                 += fdctdsp.o faandct.o           \
                                            jfdctfst.o jfdctint.o
  FFT-OBJS-$(CONFIG_HARDCODED_TABLES)    += cos_tables.o cos_fixed_tables.o
@@@ -65,11 -56,10 +64,12 @@@ OBJS-$(CONFIG_IDCTDSP)                 
                                            simple_idct.o jrevdct.o
  OBJS-$(CONFIG_INTRAX8)                 += intrax8.o intrax8dsp.o
  OBJS-$(CONFIG_LIBXVID)                 += libxvid_rc.o
 +OBJS-$(CONFIG_LLAUDDSP)                += lossless_audiodsp.o
 +OBJS-$(CONFIG_LLVIDDSP)                += lossless_videodsp.o
  OBJS-$(CONFIG_LPC)                     += lpc.o
  OBJS-$(CONFIG_LSP)                     += lsp.o
 -OBJS-$(CONFIG_MDCT)                    += mdct_fixed.o mdct_float.o
 +OBJS-$(CONFIG_MDCT)                    += mdct_fixed.o mdct_float.o mdct_fixed_32.o
+ OBJS-$(CONFIG_ME_CMP)                  += me_cmp.o
  OBJS-$(CONFIG_MPEG_ER)                 += mpeg_er.o
  OBJS-$(CONFIG_MPEGAUDIO)               += mpegaudio.o mpegaudiodata.o   \
                                            mpegaudiodecheader.o
Simple merge
Simple merge
@@@ -19,7 -18,7 +18,8 @@@ OBJS-$(CONFIG_IDCTDSP)                 
                                            arm/idctdsp_arm.o             \
                                            arm/jrevdct_arm.o             \
                                            arm/simple_idct_arm.o
 +OBJS-$(CONFIG_LLAUDDSP)                += arm/lossless_audiodsp_init_arm.o
+ OBJS-$(CONFIG_ME_CMP)                  += arm/me_cmp_init_arm.o
  OBJS-$(CONFIG_MPEGAUDIODSP)            += arm/mpegaudiodsp_init_arm.o
  OBJS-$(CONFIG_MPEGVIDEO)               += arm/mpegvideo_arm.o
  OBJS-$(CONFIG_MPEGVIDEOENC)            += arm/mpegvideoencdsp_init_arm.o
@@@ -54,8 -53,7 +54,7 @@@ ARMV5TE-OBJS-$(CONFIG_VIDEODSP)        
  ARMV5TE-OBJS-$(CONFIG_MLP_DECODER)     += arm/mlpdsp_armv5te.o
  
  ARMV6-OBJS-$(CONFIG_AC3DSP)            += arm/ac3dsp_armv6.o
- ARMV6-OBJS-$(CONFIG_DSPUTIL)           += arm/dsputil_armv6.o
 -ARMV6-OBJS-$(CONFIG_H264DSP)           += arm/h264dsp_armv6.o
 +ARMV6-OBJS-$(CONFIG_H264DSP)           += arm/startcode_armv6.o
  ARMV6-OBJS-$(CONFIG_HPELDSP)           += arm/hpeldsp_init_armv6.o      \
                                            arm/hpeldsp_armv6.o
  ARMV6-OBJS-$(CONFIG_IDCTDSP)           += arm/idctdsp_init_armv6.o      \
Simple merge
Simple merge
index 51a924b,0000000..96d8bae
mode 100644,000000..100644
--- /dev/null
@@@ -1,572 -1,0 +1,571 @@@
- #include "dsputil.h"
 +/*
 + * Copyright (C) 2004-2010 Michael Niedermayer <michaelni@gmx.at>
 + * Copyright (C) 2008 David Conrad
 + *
 + * 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
 + */
 +
 +#include "libavutil/attributes.h"
 +#include "libavutil/avassert.h"
 +#include "libavutil/common.h"
 +#include "dirac_dwt.h"
 +#include "libavcodec/x86/dirac_dwt.h"
 +
 +
 +static inline int mirror(int v, int m)
 +{
 +    while ((unsigned)v > (unsigned)m) {
 +        v = -v;
 +        if (v < 0)
 +            v += 2 * m;
 +    }
 +    return v;
 +}
 +
 +static void vertical_compose53iL0(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2,
 +                                  int width)
 +{
 +    int i;
 +
 +    for (i = 0; i < width; i++)
 +        b1[i] -= (b0[i] + b2[i] + 2) >> 2;
 +}
 +
 +
 +static av_always_inline
 +void interleave(IDWTELEM *dst, IDWTELEM *src0, IDWTELEM *src1, int w2, int add, int shift)
 +{
 +    int i;
 +    for (i = 0; i < w2; i++) {
 +        dst[2*i  ] = (src0[i] + add) >> shift;
 +        dst[2*i+1] = (src1[i] + add) >> shift;
 +    }
 +}
 +
 +static void horizontal_compose_dirac53i(IDWTELEM *b, IDWTELEM *temp, int w)
 +{
 +    const int w2 = w >> 1;
 +    int x;
 +
 +    temp[0] = COMPOSE_53iL0(b[w2], b[0], b[w2]);
 +    for (x = 1; x < w2; x++) {
 +        temp[x     ] = COMPOSE_53iL0     (b[x+w2-1], b[x     ], b[x+w2]);
 +        temp[x+w2-1] = COMPOSE_DIRAC53iH0(temp[x-1], b[x+w2-1], temp[x]);
 +    }
 +    temp[w-1] = COMPOSE_DIRAC53iH0(temp[w2-1], b[w-1], temp[w2-1]);
 +
 +    interleave(b, temp, temp+w2, w2, 1, 1);
 +}
 +
 +static void horizontal_compose_dd97i(IDWTELEM *b, IDWTELEM *tmp, int w)
 +{
 +    const int w2 = w >> 1;
 +    int x;
 +
 +    tmp[0] = COMPOSE_53iL0(b[w2], b[0], b[w2]);
 +    for (x = 1; x < w2; x++)
 +        tmp[x] = COMPOSE_53iL0(b[x+w2-1], b[x], b[x+w2]);
 +
 +    // extend the edges
 +    tmp[-1]   = tmp[0];
 +    tmp[w2+1] = tmp[w2] = tmp[w2-1];
 +
 +    for (x = 0; x < w2; x++) {
 +        b[2*x  ] = (tmp[x] + 1)>>1;
 +        b[2*x+1] = (COMPOSE_DD97iH0(tmp[x-1], tmp[x], b[x+w2], tmp[x+1], tmp[x+2]) + 1)>>1;
 +    }
 +}
 +
 +static void horizontal_compose_dd137i(IDWTELEM *b, IDWTELEM *tmp, int w)
 +{
 +    const int w2 = w >> 1;
 +    int x;
 +
 +    tmp[0] = COMPOSE_DD137iL0(b[w2], b[w2], b[0], b[w2  ], b[w2+1]);
 +    tmp[1] = COMPOSE_DD137iL0(b[w2], b[w2], b[1], b[w2+1], b[w2+2]);
 +    for (x = 2; x < w2-1; x++)
 +        tmp[x] = COMPOSE_DD137iL0(b[x+w2-2], b[x+w2-1], b[x], b[x+w2], b[x+w2+1]);
 +    tmp[w2-1] = COMPOSE_DD137iL0(b[w-3], b[w-2], b[w2-1], b[w-1], b[w-1]);
 +
 +    // extend the edges
 +    tmp[-1]   = tmp[0];
 +    tmp[w2+1] = tmp[w2] = tmp[w2-1];
 +
 +    for (x = 0; x < w2; x++) {
 +        b[2*x  ] = (tmp[x] + 1)>>1;
 +        b[2*x+1] = (COMPOSE_DD97iH0(tmp[x-1], tmp[x], b[x+w2], tmp[x+1], tmp[x+2]) + 1)>>1;
 +    }
 +}
 +
 +static av_always_inline
 +void horizontal_compose_haari(IDWTELEM *b, IDWTELEM *temp, int w, int shift)
 +{
 +    const int w2 = w >> 1;
 +    int x;
 +
 +    for (x = 0; x < w2; x++) {
 +        temp[x   ] = COMPOSE_HAARiL0(b[x   ], b[x+w2]);
 +        temp[x+w2] = COMPOSE_HAARiH0(b[x+w2], temp[x]);
 +    }
 +
 +    interleave(b, temp, temp+w2, w2, shift, shift);
 +}
 +
 +static void horizontal_compose_haar0i(IDWTELEM *b, IDWTELEM *temp, int w)
 +{
 +    horizontal_compose_haari(b, temp, w, 0);
 +}
 +
 +static void horizontal_compose_haar1i(IDWTELEM *b, IDWTELEM *temp, int w)
 +{
 +    horizontal_compose_haari(b, temp, w, 1);
 +}
 +
 +static void horizontal_compose_fidelityi(IDWTELEM *b, IDWTELEM *tmp, int w)
 +{
 +    const int w2 = w >> 1;
 +    int i, x;
 +    IDWTELEM v[8];
 +
 +    for (x = 0; x < w2; x++) {
 +        for (i = 0; i < 8; i++)
 +            v[i] = b[av_clip(x-3+i, 0, w2-1)];
 +        tmp[x] = COMPOSE_FIDELITYiH0(v[0], v[1], v[2], v[3], b[x+w2], v[4], v[5], v[6], v[7]);
 +    }
 +
 +    for (x = 0; x < w2; x++) {
 +        for (i = 0; i < 8; i++)
 +            v[i] = tmp[av_clip(x-4+i, 0, w2-1)];
 +        tmp[x+w2] = COMPOSE_FIDELITYiL0(v[0], v[1], v[2], v[3], b[x], v[4], v[5], v[6], v[7]);
 +    }
 +
 +    interleave(b, tmp+w2, tmp, w2, 0, 0);
 +}
 +
 +static void horizontal_compose_daub97i(IDWTELEM *b, IDWTELEM *temp, int w)
 +{
 +    const int w2 = w >> 1;
 +    int x, b0, b1, b2;
 +
 +    temp[0] = COMPOSE_DAUB97iL1(b[w2], b[0], b[w2]);
 +    for (x = 1; x < w2; x++) {
 +        temp[x     ] = COMPOSE_DAUB97iL1(b[x+w2-1], b[x     ], b[x+w2]);
 +        temp[x+w2-1] = COMPOSE_DAUB97iH1(temp[x-1], b[x+w2-1], temp[x]);
 +    }
 +    temp[w-1] = COMPOSE_DAUB97iH1(temp[w2-1], b[w-1], temp[w2-1]);
 +
 +    // second stage combined with interleave and shift
 +    b0 = b2 = COMPOSE_DAUB97iL0(temp[w2], temp[0], temp[w2]);
 +    b[0] = (b0 + 1) >> 1;
 +    for (x = 1; x < w2; x++) {
 +        b2 = COMPOSE_DAUB97iL0(temp[x+w2-1], temp[x     ], temp[x+w2]);
 +        b1 = COMPOSE_DAUB97iH0(          b0, temp[x+w2-1], b2        );
 +        b[2*x-1] = (b1 + 1) >> 1;
 +        b[2*x  ] = (b2 + 1) >> 1;
 +        b0 = b2;
 +    }
 +    b[w-1] = (COMPOSE_DAUB97iH0(b2, temp[w-1], b2) + 1) >> 1;
 +}
 +
 +static void vertical_compose_dirac53iH0(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, int width)
 +{
 +    int i;
 +
 +    for(i=0; i<width; i++){
 +        b1[i] = COMPOSE_DIRAC53iH0(b0[i], b1[i], b2[i]);
 +    }
 +}
 +
 +static void vertical_compose_dd97iH0(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2,
 +                                  IDWTELEM *b3, IDWTELEM *b4, int width)
 +{
 +    int i;
 +
 +    for(i=0; i<width; i++){
 +        b2[i] = COMPOSE_DD97iH0(b0[i], b1[i], b2[i], b3[i], b4[i]);
 +    }
 +}
 +
 +static void vertical_compose_dd137iL0(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2,
 +                                      IDWTELEM *b3, IDWTELEM *b4, int width)
 +{
 +    int i;
 +
 +    for(i=0; i<width; i++){
 +        b2[i] = COMPOSE_DD137iL0(b0[i], b1[i], b2[i], b3[i], b4[i]);
 +    }
 +}
 +
 +static void vertical_compose_haar(IDWTELEM *b0, IDWTELEM *b1, int width)
 +{
 +    int i;
 +
 +    for (i = 0; i < width; i++) {
 +        b0[i] = COMPOSE_HAARiL0(b0[i], b1[i]);
 +        b1[i] = COMPOSE_HAARiH0(b1[i], b0[i]);
 +    }
 +}
 +
 +static void vertical_compose_fidelityiH0(IDWTELEM *dst, IDWTELEM *b[8], int width)
 +{
 +    int i;
 +
 +    for(i=0; i<width; i++){
 +        dst[i] = COMPOSE_FIDELITYiH0(b[0][i], b[1][i], b[2][i], b[3][i], dst[i], b[4][i], b[5][i], b[6][i], b[7][i]);
 +    }
 +}
 +
 +static void vertical_compose_fidelityiL0(IDWTELEM *dst, IDWTELEM *b[8], int width)
 +{
 +    int i;
 +
 +    for(i=0; i<width; i++){
 +        dst[i] = COMPOSE_FIDELITYiL0(b[0][i], b[1][i], b[2][i], b[3][i], dst[i], b[4][i], b[5][i], b[6][i], b[7][i]);
 +    }
 +}
 +
 +static void vertical_compose_daub97iH0(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, int width)
 +{
 +    int i;
 +
 +    for(i=0; i<width; i++){
 +        b1[i] = COMPOSE_DAUB97iH0(b0[i], b1[i], b2[i]);
 +    }
 +}
 +
 +static void vertical_compose_daub97iH1(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, int width)
 +{
 +    int i;
 +
 +    for(i=0; i<width; i++){
 +        b1[i] = COMPOSE_DAUB97iH1(b0[i], b1[i], b2[i]);
 +    }
 +}
 +
 +static void vertical_compose_daub97iL0(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, int width)
 +{
 +    int i;
 +
 +    for(i=0; i<width; i++){
 +        b1[i] = COMPOSE_DAUB97iL0(b0[i], b1[i], b2[i]);
 +    }
 +}
 +
 +static void vertical_compose_daub97iL1(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, int width)
 +{
 +    int i;
 +
 +    for(i=0; i<width; i++){
 +        b1[i] = COMPOSE_DAUB97iL1(b0[i], b1[i], b2[i]);
 +    }
 +}
 +
 +
 +static void spatial_compose_dd97i_dy(DWTContext *d, int level, int width, int height, int stride)
 +{
 +    vertical_compose_3tap vertical_compose_l0 = (void*)d->vertical_compose_l0;
 +    vertical_compose_5tap vertical_compose_h0 = (void*)d->vertical_compose_h0;
 +    DWTCompose *cs = d->cs + level;
 +
 +    int i, y = cs->y;
 +    IDWTELEM *b[8];
 +    for (i = 0; i < 6; i++)
 +        b[i] = cs->b[i];
 +    b[6] = d->buffer + av_clip(y+5, 0, height-2)*stride;
 +    b[7] = d->buffer + av_clip(y+6, 1, height-1)*stride;
 +
 +        if(y+5<(unsigned)height) vertical_compose_l0(      b[5], b[6], b[7],       width);
 +        if(y+1<(unsigned)height) vertical_compose_h0(b[0], b[2], b[3], b[4], b[6], width);
 +
 +        if(y-1<(unsigned)height) d->horizontal_compose(b[0], d->temp, width);
 +        if(y+0<(unsigned)height) d->horizontal_compose(b[1], d->temp, width);
 +
 +    for (i = 0; i < 6; i++)
 +        cs->b[i] = b[i+2];
 +    cs->y += 2;
 +}
 +
 +static void spatial_compose_dirac53i_dy(DWTContext *d, int level, int width, int height, int stride)
 +{
 +    vertical_compose_3tap vertical_compose_l0 = (void*)d->vertical_compose_l0;
 +    vertical_compose_3tap vertical_compose_h0 = (void*)d->vertical_compose_h0;
 +    DWTCompose *cs = d->cs + level;
 +
 +    int y= cs->y;
 +    IDWTELEM *b[4] = { cs->b[0], cs->b[1] };
 +    b[2] = d->buffer + mirror(y+1, height-1)*stride;
 +    b[3] = d->buffer + mirror(y+2, height-1)*stride;
 +
 +        if(y+1<(unsigned)height) vertical_compose_l0(b[1], b[2], b[3], width);
 +        if(y+0<(unsigned)height) vertical_compose_h0(b[0], b[1], b[2], width);
 +
 +        if(y-1<(unsigned)height) d->horizontal_compose(b[0], d->temp, width);
 +        if(y+0<(unsigned)height) d->horizontal_compose(b[1], d->temp, width);
 +
 +    cs->b[0] = b[2];
 +    cs->b[1] = b[3];
 +    cs->y += 2;
 +}
 +
 +
 +static void spatial_compose_dd137i_dy(DWTContext *d, int level, int width, int height, int stride)
 +{
 +    vertical_compose_5tap vertical_compose_l0 = (void*)d->vertical_compose_l0;
 +    vertical_compose_5tap vertical_compose_h0 = (void*)d->vertical_compose_h0;
 +    DWTCompose *cs = d->cs + level;
 +
 +    int i, y = cs->y;
 +    IDWTELEM *b[10];
 +    for (i = 0; i < 8; i++)
 +        b[i] = cs->b[i];
 +    b[8] = d->buffer + av_clip(y+7, 0, height-2)*stride;
 +    b[9] = d->buffer + av_clip(y+8, 1, height-1)*stride;
 +
 +        if(y+5<(unsigned)height) vertical_compose_l0(b[3], b[5], b[6], b[7], b[9], width);
 +        if(y+1<(unsigned)height) vertical_compose_h0(b[0], b[2], b[3], b[4], b[6], width);
 +
 +        if(y-1<(unsigned)height) d->horizontal_compose(b[0], d->temp, width);
 +        if(y+0<(unsigned)height) d->horizontal_compose(b[1], d->temp, width);
 +
 +    for (i = 0; i < 8; i++)
 +        cs->b[i] = b[i+2];
 +    cs->y += 2;
 +}
 +
 +// haar makes the assumption that height is even (always true for dirac)
 +static void spatial_compose_haari_dy(DWTContext *d, int level, int width, int height, int stride)
 +{
 +    vertical_compose_2tap vertical_compose = (void*)d->vertical_compose;
 +    int y = d->cs[level].y;
 +    IDWTELEM *b0 = d->buffer + (y-1)*stride;
 +    IDWTELEM *b1 = d->buffer + (y  )*stride;
 +
 +    vertical_compose(b0, b1, width);
 +    d->horizontal_compose(b0, d->temp, width);
 +    d->horizontal_compose(b1, d->temp, width);
 +
 +    d->cs[level].y += 2;
 +}
 +
 +// Don't do sliced idwt for fidelity; the 9 tap filter makes it a bit annoying
 +// Fortunately, this filter isn't used in practice.
 +static void spatial_compose_fidelity(DWTContext *d, int level, int width, int height, int stride)
 +{
 +    vertical_compose_9tap vertical_compose_l0 = (void*)d->vertical_compose_l0;
 +    vertical_compose_9tap vertical_compose_h0 = (void*)d->vertical_compose_h0;
 +    int i, y;
 +    IDWTELEM *b[8];
 +
 +    for (y = 1; y < height; y += 2) {
 +        for (i = 0; i < 8; i++)
 +            b[i] = d->buffer + av_clip((y-7 + 2*i), 0, height-2)*stride;
 +        vertical_compose_h0(d->buffer + y*stride, b, width);
 +    }
 +
 +    for (y = 0; y < height; y += 2) {
 +        for (i = 0; i < 8; i++)
 +            b[i] = d->buffer + av_clip((y-7 + 2*i), 1, height-1)*stride;
 +        vertical_compose_l0(d->buffer + y*stride, b, width);
 +    }
 +
 +    for (y = 0; y < height; y++)
 +        d->horizontal_compose(d->buffer + y*stride, d->temp, width);
 +
 +    d->cs[level].y = height+1;
 +}
 +
 +static void spatial_compose_daub97i_dy(DWTContext *d, int level, int width, int height, int stride)
 +{
 +    vertical_compose_3tap vertical_compose_l0 = (void*)d->vertical_compose_l0;
 +    vertical_compose_3tap vertical_compose_h0 = (void*)d->vertical_compose_h0;
 +    vertical_compose_3tap vertical_compose_l1 = (void*)d->vertical_compose_l1;
 +    vertical_compose_3tap vertical_compose_h1 = (void*)d->vertical_compose_h1;
 +    DWTCompose *cs = d->cs + level;
 +
 +    int i, y = cs->y;
 +    IDWTELEM *b[6];
 +    for (i = 0; i < 4; i++)
 +        b[i] = cs->b[i];
 +    b[4] = d->buffer + mirror(y+3, height-1)*stride;
 +    b[5] = d->buffer + mirror(y+4, height-1)*stride;
 +
 +        if(y+3<(unsigned)height) vertical_compose_l1(b[3], b[4], b[5], width);
 +        if(y+2<(unsigned)height) vertical_compose_h1(b[2], b[3], b[4], width);
 +        if(y+1<(unsigned)height) vertical_compose_l0(b[1], b[2], b[3], width);
 +        if(y+0<(unsigned)height) vertical_compose_h0(b[0], b[1], b[2], width);
 +
 +        if(y-1<(unsigned)height) d->horizontal_compose(b[0], d->temp, width);
 +        if(y+0<(unsigned)height) d->horizontal_compose(b[1], d->temp, width);
 +
 +    for (i = 0; i < 4; i++)
 +        cs->b[i] = b[i+2];
 +    cs->y += 2;
 +}
 +
 +
 +static void spatial_compose97i_init2(DWTCompose *cs, IDWTELEM *buffer, int height, int stride)
 +{
 +    cs->b[0] = buffer + mirror(-3-1, height-1)*stride;
 +    cs->b[1] = buffer + mirror(-3  , height-1)*stride;
 +    cs->b[2] = buffer + mirror(-3+1, height-1)*stride;
 +    cs->b[3] = buffer + mirror(-3+2, height-1)*stride;
 +    cs->y = -3;
 +}
 +
 +static void spatial_compose53i_init2(DWTCompose *cs, IDWTELEM *buffer, int height, int stride)
 +{
 +    cs->b[0] = buffer + mirror(-1-1, height-1)*stride;
 +    cs->b[1] = buffer + mirror(-1  , height-1)*stride;
 +    cs->y = -1;
 +}
 +
 +static void spatial_compose_dd97i_init(DWTCompose *cs, IDWTELEM *buffer, int height, int stride)
 +{
 +    cs->b[0] = buffer + av_clip(-5-1, 0, height-2)*stride;
 +    cs->b[1] = buffer + av_clip(-5  , 1, height-1)*stride;
 +    cs->b[2] = buffer + av_clip(-5+1, 0, height-2)*stride;
 +    cs->b[3] = buffer + av_clip(-5+2, 1, height-1)*stride;
 +    cs->b[4] = buffer + av_clip(-5+3, 0, height-2)*stride;
 +    cs->b[5] = buffer + av_clip(-5+4, 1, height-1)*stride;
 +    cs->y = -5;
 +}
 +
 +static void spatial_compose_dd137i_init(DWTCompose *cs, IDWTELEM *buffer, int height, int stride)
 +{
 +    cs->b[0] = buffer + av_clip(-5-1, 0, height-2)*stride;
 +    cs->b[1] = buffer + av_clip(-5  , 1, height-1)*stride;
 +    cs->b[2] = buffer + av_clip(-5+1, 0, height-2)*stride;
 +    cs->b[3] = buffer + av_clip(-5+2, 1, height-1)*stride;
 +    cs->b[4] = buffer + av_clip(-5+3, 0, height-2)*stride;
 +    cs->b[5] = buffer + av_clip(-5+4, 1, height-1)*stride;
 +    cs->b[6] = buffer + av_clip(-5+5, 0, height-2)*stride;
 +    cs->b[7] = buffer + av_clip(-5+6, 1, height-1)*stride;
 +    cs->y = -5;
 +}
 +
 +int ff_spatial_idwt_init2(DWTContext *d, IDWTELEM *buffer, int width, int height,
 +                          int stride, enum dwt_type type, int decomposition_count,
 +                          IDWTELEM *temp)
 +{
 +    int level;
 +
 +    d->buffer = buffer;
 +    d->width = width;
 +    d->height = height;
 +    d->stride = stride;
 +    d->decomposition_count = decomposition_count;
 +    d->temp = temp + 8;
 +
 +    for(level=decomposition_count-1; level>=0; level--){
 +        int hl = height >> level;
 +        int stride_l = stride << level;
 +
 +        switch(type){
 +        case DWT_DIRAC_DD9_7:
 +            spatial_compose_dd97i_init(d->cs+level, buffer, hl, stride_l);
 +            break;
 +        case DWT_DIRAC_LEGALL5_3:
 +            spatial_compose53i_init2(d->cs+level, buffer, hl, stride_l);
 +            break;
 +        case DWT_DIRAC_DD13_7:
 +            spatial_compose_dd137i_init(d->cs+level, buffer, hl, stride_l);
 +            break;
 +        case DWT_DIRAC_HAAR0:
 +        case DWT_DIRAC_HAAR1:
 +            d->cs[level].y = 1;
 +            break;
 +        case DWT_DIRAC_DAUB9_7:
 +            spatial_compose97i_init2(d->cs+level, buffer, hl, stride_l);
 +            break;
 +        default:
 +            d->cs[level].y = 0;
 +            break;
 +        }
 +    }
 +
 +    switch (type) {
 +    case DWT_DIRAC_DD9_7:
 +        d->spatial_compose = spatial_compose_dd97i_dy;
 +        d->vertical_compose_l0 = (void*)vertical_compose53iL0;
 +        d->vertical_compose_h0 = (void*)vertical_compose_dd97iH0;
 +        d->horizontal_compose = horizontal_compose_dd97i;
 +        d->support = 7;
 +        break;
 +    case DWT_DIRAC_LEGALL5_3:
 +        d->spatial_compose = spatial_compose_dirac53i_dy;
 +        d->vertical_compose_l0 = (void*)vertical_compose53iL0;
 +        d->vertical_compose_h0 = (void*)vertical_compose_dirac53iH0;
 +        d->horizontal_compose = horizontal_compose_dirac53i;
 +        d->support = 3;
 +        break;
 +    case DWT_DIRAC_DD13_7:
 +        d->spatial_compose = spatial_compose_dd137i_dy;
 +        d->vertical_compose_l0 = (void*)vertical_compose_dd137iL0;
 +        d->vertical_compose_h0 = (void*)vertical_compose_dd97iH0;
 +        d->horizontal_compose = horizontal_compose_dd137i;
 +        d->support = 7;
 +        break;
 +    case DWT_DIRAC_HAAR0:
 +    case DWT_DIRAC_HAAR1:
 +        d->spatial_compose = spatial_compose_haari_dy;
 +        d->vertical_compose = (void*)vertical_compose_haar;
 +        if (type == DWT_DIRAC_HAAR0)
 +            d->horizontal_compose = horizontal_compose_haar0i;
 +        else
 +            d->horizontal_compose = horizontal_compose_haar1i;
 +        d->support = 1;
 +        break;
 +    case DWT_DIRAC_FIDELITY:
 +        d->spatial_compose = spatial_compose_fidelity;
 +        d->vertical_compose_l0 = (void*)vertical_compose_fidelityiL0;
 +        d->vertical_compose_h0 = (void*)vertical_compose_fidelityiH0;
 +        d->horizontal_compose = horizontal_compose_fidelityi;
 +        d->support = 0; // not really used
 +        break;
 +    case DWT_DIRAC_DAUB9_7:
 +        d->spatial_compose = spatial_compose_daub97i_dy;
 +        d->vertical_compose_l0 = (void*)vertical_compose_daub97iL0;
 +        d->vertical_compose_h0 = (void*)vertical_compose_daub97iH0;
 +        d->vertical_compose_l1 = (void*)vertical_compose_daub97iL1;
 +        d->vertical_compose_h1 = (void*)vertical_compose_daub97iH1;
 +        d->horizontal_compose = horizontal_compose_daub97i;
 +        d->support = 5;
 +        break;
 +    default:
 +        av_log(NULL, AV_LOG_ERROR, "Unknown wavelet type %d\n", type);
 +        return -1;
 +    }
 +
 +    if (HAVE_MMX) ff_spatial_idwt_init_mmx(d, type);
 +
 +    return 0;
 +}
 +
 +void ff_spatial_idwt_slice2(DWTContext *d, int y)
 +{
 +    int level, support = d->support;
 +
 +    for (level = d->decomposition_count-1; level >= 0; level--) {
 +        int wl = d->width  >> level;
 +        int hl = d->height >> level;
 +        int stride_l = d->stride << level;
 +
 +        while (d->cs[level].y <= FFMIN((y>>level)+support, hl))
 +            d->spatial_compose(d, level, wl, hl, stride_l);
 +    }
 +}
 +
index 429241d,0000000..3b8c39d
mode 100644,000000..100644
--- /dev/null
@@@ -1,201 -1,0 +1,201 @@@
- #include "dsputil.h"
 +/*
 + * Copyright (C) 2009 David Conrad
 + *
 + * 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
 + */
 +
++#include "avcodec.h"
 +#include "diracdsp.h"
 +#include "libavcodec/x86/diracdsp_mmx.h"
 +
 +#define FILTER(src, stride)                                     \
 +    ((21*((src)[ 0*stride] + (src)[1*stride])                   \
 +      -7*((src)[-1*stride] + (src)[2*stride])                   \
 +      +3*((src)[-2*stride] + (src)[3*stride])                   \
 +      -1*((src)[-3*stride] + (src)[4*stride]) + 16) >> 5)
 +
 +static void dirac_hpel_filter(uint8_t *dsth, uint8_t *dstv, uint8_t *dstc, const uint8_t *src,
 +                              int stride, int width, int height)
 +{
 +    int x, y;
 +
 +    for (y = 0; y < height; y++) {
 +        for (x = -3; x < width+5; x++)
 +            dstv[x] = av_clip_uint8(FILTER(src+x, stride));
 +
 +        for (x = 0; x < width; x++)
 +            dstc[x] = av_clip_uint8(FILTER(dstv+x, 1));
 +
 +        for (x = 0; x < width; x++)
 +            dsth[x] = av_clip_uint8(FILTER(src+x, 1));
 +
 +        src  += stride;
 +        dsth += stride;
 +        dstv += stride;
 +        dstc += stride;
 +    }
 +}
 +
 +#define PIXOP_BILINEAR(PFX, OP, WIDTH)                                  \
 +    static void ff_ ## PFX ## _dirac_pixels ## WIDTH ## _bilinear_c(uint8_t *dst, const uint8_t *src[5], int stride, int h) \
 +    {                                                                   \
 +        int x;                                                          \
 +        const uint8_t *s0 = src[0];                                     \
 +        const uint8_t *s1 = src[1];                                     \
 +        const uint8_t *s2 = src[2];                                     \
 +        const uint8_t *s3 = src[3];                                     \
 +        const uint8_t *w  = src[4];                                     \
 +                                                                        \
 +        while (h--) {                                                   \
 +            for (x = 0; x < WIDTH; x++) {                               \
 +                OP(dst[x], (s0[x]*w[0] + s1[x]*w[1] + s2[x]*w[2] + s3[x]*w[3] + 8) >> 4); \
 +            }                                                           \
 +                                                                        \
 +            dst += stride;                                              \
 +            s0 += stride;                                               \
 +            s1 += stride;                                               \
 +            s2 += stride;                                               \
 +            s3 += stride;                                               \
 +        }                                                               \
 +    }
 +
 +#define OP_PUT(dst, val) (dst) = (val)
 +#define OP_AVG(dst, val) (dst) = (((dst) + (val) + 1)>>1)
 +
 +PIXOP_BILINEAR(put, OP_PUT, 8)
 +PIXOP_BILINEAR(put, OP_PUT, 16)
 +PIXOP_BILINEAR(put, OP_PUT, 32)
 +PIXOP_BILINEAR(avg, OP_AVG, 8)
 +PIXOP_BILINEAR(avg, OP_AVG, 16)
 +PIXOP_BILINEAR(avg, OP_AVG, 32)
 +
 +#define op_scale1(x)  block[x] = av_clip_uint8( (block[x]*weight + (1<<(log2_denom-1))) >> log2_denom)
 +#define op_scale2(x)  dst[x] = av_clip_uint8( (src[x]*weights + dst[x]*weightd + (1<<(log2_denom-1))) >> log2_denom)
 +
 +#define DIRAC_WEIGHT(W)                                                 \
 +    static void weight_dirac_pixels ## W ## _c(uint8_t *block, int stride, int log2_denom, \
 +                                               int weight, int h) {     \
 +        int x;                                                          \
 +        while (h--) {                                                   \
 +            for (x = 0; x < W; x++) {                                   \
 +                op_scale1(x);                                           \
 +                op_scale1(x+1);                                         \
 +            }                                                           \
 +            block += stride;                                            \
 +        }                                                               \
 +    }                                                                   \
 +    static void biweight_dirac_pixels ## W ## _c(uint8_t *dst, const uint8_t *src, int stride, int log2_denom, \
 +                                                 int weightd, int weights, int h) { \
 +        int x;                                                          \
 +        while (h--) {                                                   \
 +            for (x = 0; x < W; x++) {                                   \
 +                op_scale2(x);                                           \
 +                op_scale2(x+1);                                         \
 +            }                                                           \
 +            dst += stride;                                              \
 +            src += stride;                                              \
 +        }                                                               \
 +    }
 +
 +DIRAC_WEIGHT(8)
 +DIRAC_WEIGHT(16)
 +DIRAC_WEIGHT(32)
 +
 +#define ADD_OBMC(xblen)                                                 \
 +    static void add_obmc ## xblen ## _c(uint16_t *dst, const uint8_t *src, int stride, \
 +                                        const uint8_t *obmc_weight, int yblen) \
 +    {                                                                   \
 +        int x;                                                          \
 +        while (yblen--) {                                               \
 +            for (x = 0; x < xblen; x += 2) {                            \
 +                dst[x  ] += src[x  ] * obmc_weight[x  ];                \
 +                dst[x+1] += src[x+1] * obmc_weight[x+1];                \
 +            }                                                           \
 +            dst += stride;                                              \
 +            src += stride;                                              \
 +            obmc_weight += 32;                                          \
 +        }                                                               \
 +    }
 +
 +ADD_OBMC(8)
 +ADD_OBMC(16)
 +ADD_OBMC(32)
 +
 +static void put_signed_rect_clamped_c(uint8_t *dst, int dst_stride, const int16_t *src, int src_stride, int width, int height)
 +{
 +    int x, y;
 +    for (y = 0; y < height; y++) {
 +        for (x = 0; x < width; x+=4) {
 +            dst[x  ] = av_clip_uint8(src[x  ] + 128);
 +            dst[x+1] = av_clip_uint8(src[x+1] + 128);
 +            dst[x+2] = av_clip_uint8(src[x+2] + 128);
 +            dst[x+3] = av_clip_uint8(src[x+3] + 128);
 +        }
 +        dst += dst_stride;
 +        src += src_stride;
 +    }
 +}
 +
 +static void add_rect_clamped_c(uint8_t *dst, const uint16_t *src, int stride,
 +                               const int16_t *idwt, int idwt_stride,
 +                               int width, int height)
 +{
 +    int x, y;
 +
 +    for (y = 0; y < height; y++) {
 +        for (x = 0; x < width; x+=2) {
 +            dst[x  ] = av_clip_uint8(((src[x  ]+32)>>6) + idwt[x  ]);
 +            dst[x+1] = av_clip_uint8(((src[x+1]+32)>>6) + idwt[x+1]);
 +        }
 +        dst += stride;
 +        src += stride;
 +        idwt += idwt_stride;
 +    }
 +}
 +
 +#define PIXFUNC(PFX, WIDTH)                                             \
 +    c->PFX ## _dirac_pixels_tab[WIDTH>>4][0] = ff_ ## PFX ## _dirac_pixels ## WIDTH ## _c; \
 +    c->PFX ## _dirac_pixels_tab[WIDTH>>4][1] = ff_ ## PFX ## _dirac_pixels ## WIDTH ## _l2_c; \
 +    c->PFX ## _dirac_pixels_tab[WIDTH>>4][2] = ff_ ## PFX ## _dirac_pixels ## WIDTH ## _l4_c; \
 +    c->PFX ## _dirac_pixels_tab[WIDTH>>4][3] = ff_ ## PFX ## _dirac_pixels ## WIDTH ## _bilinear_c
 +
 +void ff_diracdsp_init(DiracDSPContext *c)
 +{
 +    c->dirac_hpel_filter = dirac_hpel_filter;
 +    c->add_rect_clamped = add_rect_clamped_c;
 +    c->put_signed_rect_clamped = put_signed_rect_clamped_c;
 +
 +    c->add_dirac_obmc[0] = add_obmc8_c;
 +    c->add_dirac_obmc[1] = add_obmc16_c;
 +    c->add_dirac_obmc[2] = add_obmc32_c;
 +
 +    c->weight_dirac_pixels_tab[0] = weight_dirac_pixels8_c;
 +    c->weight_dirac_pixels_tab[1] = weight_dirac_pixels16_c;
 +    c->weight_dirac_pixels_tab[2] = weight_dirac_pixels32_c;
 +    c->biweight_dirac_pixels_tab[0] = biweight_dirac_pixels8_c;
 +    c->biweight_dirac_pixels_tab[1] = biweight_dirac_pixels16_c;
 +    c->biweight_dirac_pixels_tab[2] = biweight_dirac_pixels32_c;
 +
 +    PIXFUNC(put, 8);
 +    PIXFUNC(put, 16);
 +    PIXFUNC(put, 32);
 +    PIXFUNC(avg, 8);
 +    PIXFUNC(avg, 16);
 +    PIXFUNC(avg, 32);
 +
 +    if (HAVE_MMX && HAVE_YASM) ff_diracdsp_init_mmx(c);
 +}
diff --cc libavcodec/dv.h
Simple merge
index 4b03e39,0000000..6e2352d
mode 100644,000000..100644
--- /dev/null
@@@ -1,116 -1,0 +1,115 @@@
- #include "dsputil.h"
 +/*
 + * DVD navigation block parser for FFmpeg
 + * Copyright (c) 2013 The FFmpeg Project
 + *
 + * 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
 + */
 +#include "avcodec.h"
 +#include "get_bits.h"
 +#include "parser.h"
 +
 +#define PCI_SIZE  980
 +#define DSI_SIZE 1018
 +
 +/* parser definition */
 +typedef struct DVDNavParseContext {
 +    uint32_t     lba;
 +    uint8_t      buffer[PCI_SIZE+DSI_SIZE];
 +    int          copied;
 +} DVDNavParseContext;
 +
 +static av_cold int dvd_nav_parse_init(AVCodecParserContext *s)
 +{
 +    DVDNavParseContext *pc = s->priv_data;
 +
 +    pc->lba    = 0xFFFFFFFF;
 +    pc->copied = 0;
 +    return 0;
 +}
 +
 +static int dvd_nav_parse(AVCodecParserContext *s,
 +                         AVCodecContext *avctx,
 +                         const uint8_t **poutbuf, int *poutbuf_size,
 +                         const uint8_t *buf, int buf_size)
 +{
 +    DVDNavParseContext *pc1 = s->priv_data;
 +    int lastPacket          = 0;
 +    int valid               = 0;
 +
 +    s->pict_type = AV_PICTURE_TYPE_NONE;
 +
 +    avctx->time_base.num = 1;
 +    avctx->time_base.den = 90000;
 +
 +    if (buf && buf_size) {
 +        switch(buf[0]) {
 +            case 0x00:
 +                if (buf_size == PCI_SIZE) {
 +                    /* PCI */
 +                    uint32_t lba      = AV_RB32(&buf[0x01]);
 +                    uint32_t startpts = AV_RB32(&buf[0x0D]);
 +                    uint32_t endpts   = AV_RB32(&buf[0x11]);
 +
 +                    if (endpts > startpts) {
 +                        pc1->lba    = lba;
 +                        s->pts      = (int64_t)startpts;
 +                        s->duration = endpts - startpts;
 +
 +                        memcpy(pc1->buffer, buf, PCI_SIZE);
 +                        pc1->copied = PCI_SIZE;
 +                        valid       = 1;
 +                    }
 +                }
 +                break;
 +
 +            case 0x01:
 +                if ((buf_size == DSI_SIZE) && (pc1->copied == PCI_SIZE)) {
 +                    /* DSI */
 +                    uint32_t lba = AV_RB32(&buf[0x05]);
 +
 +                    if (lba == pc1->lba) {
 +                        memcpy(pc1->buffer + pc1->copied, buf, DSI_SIZE);
 +                        lastPacket  = 1;
 +                        valid       = 1;
 +                    }
 +                }
 +                break;
 +        }
 +    }
 +
 +    if (!valid || lastPacket) {
 +        pc1->copied = 0;
 +        pc1->lba    = 0xFFFFFFFF;
 +    }
 +
 +    if (lastPacket) {
 +        *poutbuf      = pc1->buffer;
 +        *poutbuf_size = sizeof(pc1->buffer);
 +    } else {
 +        *poutbuf      = NULL;
 +        *poutbuf_size = 0;
 +    }
 +
 +    return buf_size;
 +}
 +
 +AVCodecParser ff_dvd_nav_parser = {
 +    .codec_ids      = { AV_CODEC_ID_DVD_NAV },
 +    .priv_data_size = sizeof(DVDNavParseContext),
 +    .parser_init    = dvd_nav_parse_init,
 +    .parser_parse   = dvd_nav_parse,
 +};
@@@ -69,14 -65,13 +69,14 @@@ static av_cold int dvvideo_encode_init(
  
      dv_vlc_map_tableinit();
  
-     memset(&dsp,0, sizeof(dsp));
-     ff_dsputil_init(&dsp, avctx);
++    memset(&mecc,0, sizeof(mecc));
      ff_fdctdsp_init(&fdsp, avctx);
+     ff_me_cmp_init(&mecc, avctx);
      ff_pixblockdsp_init(&pdsp, avctx);
-     ff_set_cmp(&dsp, dsp.ildct_cmp, avctx->ildct_cmp);
+     ff_set_cmp(&mecc, mecc.ildct_cmp, avctx->ildct_cmp);
  
      s->get_pixels = pdsp.get_pixels;
-     s->ildct_cmp  = dsp.ildct_cmp[5];
+     s->ildct_cmp  = mecc.ildct_cmp[5];
  
      s->fdct[0]    = fdsp.fdct;
      s->fdct[1]    = fdsp.fdct248;
@@@ -739,12 -715,11 +739,12 @@@ static int is_intra_more_likely(ERConte
                  } else {
                      ff_thread_await_progress(s->last_pic.tf, mb_y, 0);
                  }
-                 is_intra_likely += s->dsp->sad[0](NULL, last_mb_ptr, mb_ptr,
-                                                  linesize[0], 16);
+                 is_intra_likely += s->mecc->sad[0](NULL, last_mb_ptr, mb_ptr,
+                                                    linesize[0], 16);
 +                // FIXME need await_progress() here
-                 is_intra_likely -= s->dsp->sad[0](NULL, last_mb_ptr,
-                                                  last_mb_ptr + linesize[0] * 16,
-                                                  linesize[0], 16);
+                 is_intra_likely -= s->mecc->sad[0](NULL, last_mb_ptr,
+                                                    last_mb_ptr + linesize[0] * 16,
+                                                    linesize[0], 16);
              } else {
                  if (IS_INTRA(s->cur_pic.mb_type[mb_xy]))
                     is_intra_likely++;
Simple merge
@@@ -1264,9 -1233,8 +1264,9 @@@ int ff_h264_set_parameter_from_sps(H264
              ff_h264qpel_init(&h->h264qpel, h->sps.bit_depth_luma);
              ff_h264_pred_init(&h->hpc, h->avctx->codec_id, h->sps.bit_depth_luma,
                                h->sps.chroma_format_idc);
 +
              if (CONFIG_ERROR_RESILIENCE)
-                 ff_dsputil_init(&h->dsp, h->avctx);
+                 ff_me_cmp_init(&h->mecc, h->avctx);
              ff_videodsp_init(&h->vdsp, h->sps.bit_depth_luma);
          } else {
              av_log(h->avctx, AV_LOG_ERROR, "Unsupported bit depth %d\n",
Simple merge
@@@ -1202,9 -1118,7 +1201,9 @@@ static int h264_slice_header_init(H264C
              if (!c)
                  return AVERROR(ENOMEM);
              c->avctx             = h->avctx;
 -            c->mecc              = h->mecc;
 +            if (CONFIG_ERROR_RESILIENCE) {
-                 c->dsp               = h->dsp;
++                c->mecc              = h->mecc;
 +            }
              c->vdsp              = h->vdsp;
              c->h264dsp           = h->h264dsp;
              c->h264qpel          = h->h264qpel;
@@@ -1,34 -1,4 +1,33 @@@
  LIBAVCODEC_$MAJOR {
          global: av*;
-                 dsputil_init;
-                 ff_dsputil_init;
 +                #deprecated, remove after next bump
 +                audio_resample;
 +                audio_resample_close;
 +                ff_find_pix_fmt;
 +                ff_framenum_to_drop_timecode;
 +                ff_framenum_to_smtpe_timecode;
 +                ff_raw_pix_fmt_tags;
 +                ff_init_smtpe_timecode;
 +                ff_fft*;
 +                ff_mdct*;
 +                ff_dct*;
 +                ff_rdft*;
 +                ff_prores_idct_put_10_sse2;
 +                ff_simple_idct*;
 +                ff_aanscales;
 +                ff_faan*;
 +                ff_mmx_idct;
 +                ff_fdct*;
 +                fdct_ifast;
 +                j_rev_dct;
 +                ff_mmxext_idct;
 +                ff_idct_xvid*;
 +                ff_jpeg_fdct*;
 +                ff_dnxhd_get_cid_table;
 +                ff_dnxhd_cid_table;
 +                ff_idctdsp_init;
 +                ff_fdctdsp_init;
 +                ff_pixblockdsp_init;
++                ff_me_cmp_init;
          local:  *;
  };
@@@ -1,11 -1,7 +1,7 @@@
  /*
-  * DSP utils
-  * Copyright (c) 2000, 2001 Fabrice Bellard
-  * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
-  *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * FFmpeg is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 2.1 of the License, or (at your option) any later version.
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
- /**
-  * @file
-  * DSP utils
-  */
  #include "libavutil/attributes.h"
 +#include "libavutil/internal.h"
  #include "avcodec.h"
  #include "copy_block.h"
- #include "dsputil.h"
  #include "simple_idct.h"
+ #include "me_cmp.h"
  #include "mpegvideo.h"
  #include "config.h"
  
@@@ -916,31 -890,8 +906,31 @@@ av_cold void ff_me_cmp_init_static(void
          ff_square_tab[i] = (i - 256) * (i - 256);
  }
  
- av_cold void ff_dsputil_init(DSPContext *c, AVCodecContext *avctx)
 +int ff_check_alignment(void)
 +{
 +    static int did_fail = 0;
 +    LOCAL_ALIGNED_16(int, aligned, [4]);
 +
 +    if ((intptr_t)aligned & 15) {
 +        if (!did_fail) {
 +#if HAVE_MMX || HAVE_ALTIVEC
 +            av_log(NULL, AV_LOG_ERROR,
 +                "Compiler did not align stack variables. Libavcodec has been miscompiled\n"
 +                "and may be very slow or crash. This is not a bug in libavcodec,\n"
 +                "but in the compiler. You may try recompiling using gcc >= 4.2.\n"
 +                "Do not report crashes to FFmpeg developers.\n");
 +#endif
 +            did_fail=1;
 +        }
 +        return -1;
 +    }
 +    return 0;
 +}
 +
+ av_cold void ff_me_cmp_init(MECmpContext *c, AVCodecContext *avctx)
  {
 +    ff_check_alignment();
 +
      c->sum_abs_dctelem = sum_abs_dctelem_c;
  
      /* TODO [0] 16  [1] 8 */
      c->vsse[5] = vsse_intra8_c;
      c->nsse[0] = nsse16_c;
      c->nsse[1] = nsse8_c;
 +#if CONFIG_SNOW_DECODER || CONFIG_SNOW_ENCODER
 +    ff_dsputil_init_dwt(c);
 +#endif
  
-         ff_dsputil_init_alpha(c, avctx);
 +    if (ARCH_ALPHA)
++        ff_me_cmp_init_alpha(c, avctx);
      if (ARCH_ARM)
-         ff_dsputil_init_arm(c, avctx);
+         ff_me_cmp_init_arm(c, avctx);
      if (ARCH_PPC)
-         ff_dsputil_init_ppc(c, avctx);
+         ff_me_cmp_init_ppc(c, avctx);
      if (ARCH_X86)
-         ff_dsputil_init_x86(c, avctx);
- }
- av_cold void dsputil_init(DSPContext* c, AVCodecContext *avctx)
- {
-     ff_dsputil_init(c, avctx);
- }
- av_cold void avpriv_dsputil_init(DSPContext *c, AVCodecContext *avctx)
- {
-     ff_dsputil_init(c, avctx);
+         ff_me_cmp_init_x86(c, avctx);
  }
@@@ -1,11 -1,7 +1,7 @@@
  /*
-  * DSP utils
-  * Copyright (c) 2000, 2001, 2002 Fabrice Bellard
-  * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
-  *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * FFmpeg is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 2.1 of the License, or (at your option) any later version.
@@@ -87,22 -59,15 +75,20 @@@ typedef struct MECmpContext 
      me_cmp_func frame_skip_cmp[6]; // only width 8 used
  
      me_cmp_func pix_abs[2][4];
- } DSPContext;
+ } MECmpContext;
  
- void ff_dsputil_static_init(void);
- void ff_dsputil_init(DSPContext *p, AVCodecContext *avctx);
- void avpriv_dsputil_init(DSPContext* p, AVCodecContext *avctx);
- attribute_deprecated void dsputil_init(DSPContext* c, AVCodecContext *avctx);
+ void ff_me_cmp_init_static(void);
  
- void ff_set_cmp(DSPContext *c, me_cmp_func *cmp, int type);
 +int ff_check_alignment(void);
 +
+ void ff_me_cmp_init(MECmpContext *c, AVCodecContext *avctx);
++void ff_me_cmp_init_alpha(MECmpContext *c, AVCodecContext *avctx);
+ void ff_me_cmp_init_arm(MECmpContext *c, AVCodecContext *avctx);
+ void ff_me_cmp_init_ppc(MECmpContext *c, AVCodecContext *avctx);
+ void ff_me_cmp_init_x86(MECmpContext *c, AVCodecContext *avctx);
  
- void ff_dsputil_init_alpha(DSPContext* c, AVCodecContext *avctx);
- void ff_dsputil_init_arm(DSPContext *c, AVCodecContext *avctx);
- void ff_dsputil_init_ppc(DSPContext *c, AVCodecContext *avctx);
- void ff_dsputil_init_x86(DSPContext *c, AVCodecContext *avctx);
+ void ff_set_cmp(MECmpContext *c, me_cmp_func *cmp, int type);
  
- void ff_dsputil_init_dwt(DSPContext *c);
++void ff_dsputil_init_dwt(MECmpContext *c);
 +
- #endif /* AVCODEC_DSPUTIL_H */
+ #endif /* AVCODEC_ME_CMP_H */
index 7308717,0000000..7cfe41c
mode 100644,000000..100644
--- /dev/null
@@@ -1,152 -1,0 +1,152 @@@
- #include "dsputil.h"
 +/*
 + * (c) 2001 Fabrice Bellard
 + *
 + * 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
 + */
 +
 +/**
 + * @file
 + * motion test.
 + */
 +
 +#include <stdlib.h>
 +#include <stdio.h>
 +#include <string.h>
 +
 +#include "config.h"
-     DSPContext cctx, mmxctx;
++#include "me_cmp.h"
 +#include "libavutil/internal.h"
 +#include "libavutil/lfg.h"
 +#include "libavutil/mem.h"
 +#include "libavutil/time.h"
 +
 +#undef printf
 +
 +#define WIDTH 64
 +#define HEIGHT 64
 +
 +static uint8_t img1[WIDTH * HEIGHT];
 +static uint8_t img2[WIDTH * HEIGHT];
 +
 +static void fill_random(uint8_t *tab, int size)
 +{
 +    int i;
 +    AVLFG prng;
 +
 +    av_lfg_init(&prng, 1);
 +    for(i=0;i<size;i++) {
 +        tab[i] = av_lfg_get(&prng) % 256;
 +    }
 +}
 +
 +static void help(void)
 +{
 +    printf("motion-test [-h]\n"
 +           "test motion implementations\n");
 +}
 +
 +#define NB_ITS 500
 +
 +int dummy;
 +
 +static void test_motion(const char *name,
 +                 me_cmp_func test_func, me_cmp_func ref_func)
 +{
 +    int x, y, d1, d2, it;
 +    uint8_t *ptr;
 +    int64_t ti;
 +    printf("testing '%s'\n", name);
 +
 +    /* test correctness */
 +    for(it=0;it<20;it++) {
 +
 +        fill_random(img1, WIDTH * HEIGHT);
 +        fill_random(img2, WIDTH * HEIGHT);
 +
 +        for(y=0;y<HEIGHT-17;y++) {
 +            for(x=0;x<WIDTH-17;x++) {
 +                ptr = img2 + y * WIDTH + x;
 +                d1 = test_func(NULL, img1, ptr, WIDTH, 8);
 +                d2 = ref_func(NULL, img1, ptr, WIDTH, 8);
 +                if (d1 != d2) {
 +                    printf("error: mmx=%d c=%d\n", d1, d2);
 +                }
 +            }
 +        }
 +    }
 +    emms_c();
 +
 +    /* speed test */
 +    ti = av_gettime_relative();
 +    d1 = 0;
 +    for(it=0;it<NB_ITS;it++) {
 +        for(y=0;y<HEIGHT-17;y++) {
 +            for(x=0;x<WIDTH-17;x++) {
 +                ptr = img2 + y * WIDTH + x;
 +                d1 += test_func(NULL, img1, ptr, WIDTH, 8);
 +            }
 +        }
 +    }
 +    emms_c();
 +    dummy = d1; /* avoid optimization */
 +    ti = av_gettime_relative() - ti;
 +
 +    printf("  %0.0f kop/s\n",
 +           (double)NB_ITS * (WIDTH - 16) * (HEIGHT - 16) /
 +           (double)(ti / 1000.0));
 +}
 +
 +
 +int main(int argc, char **argv)
 +{
 +    AVCodecContext *ctx;
 +    int c;
-     ff_dsputil_init(&cctx, ctx);
++    MECmpContext cctx, mmxctx;
 +    int flags[2] = { AV_CPU_FLAG_MMX, AV_CPU_FLAG_MMXEXT };
 +    int flags_size = HAVE_MMXEXT ? 2 : 1;
 +
 +    if (argc > 1) {
 +        help();
 +        return 1;
 +    }
 +
 +    printf("ffmpeg motion test\n");
 +
 +    ctx = avcodec_alloc_context3(NULL);
 +    ctx->flags |= CODEC_FLAG_BITEXACT;
 +    av_force_cpu_flags(0);
 +    memset(&cctx, 0, sizeof(cctx));
-         ff_dsputil_init(&mmxctx, ctx);
++    ff_me_cmp_init(&cctx, ctx);
 +    for (c = 0; c < flags_size; c++) {
 +        int x;
 +        av_force_cpu_flags(flags[c]);
 +        memset(&mmxctx, 0, sizeof(mmxctx));
++        ff_me_cmp_init(&mmxctx, ctx);
 +
 +        for (x = 0; x < 2; x++) {
 +            printf("%s for %dx%d pixels\n", c ? "mmx2" : "mmx",
 +                   x ? 8 : 16, x ? 8 : 16);
 +            test_motion("mmx",     mmxctx.pix_abs[x][0], cctx.pix_abs[x][0]);
 +            test_motion("mmx_x2",  mmxctx.pix_abs[x][1], cctx.pix_abs[x][1]);
 +            test_motion("mmx_y2",  mmxctx.pix_abs[x][2], cctx.pix_abs[x][2]);
 +            test_motion("mmx_xy2", mmxctx.pix_abs[x][3], cctx.pix_abs[x][3]);
 +        }
 +    }
 +    av_free(ctx);
 +
 +    return 0;
 +}
@@@ -360,16 -361,12 +360,14 @@@ int ff_init_me(MpegEncContext *s)
      /* 8x8 fullpel search would need a 4x4 chroma compare, which we do
       * not have yet, and even if we had, the motion estimation code
       * does not expect it. */
-     if(s->codec_id != AV_CODEC_ID_SNOW){
-         if((c->avctx->me_cmp&FF_CMP_CHROMA)/* && !s->dsp.me_cmp[2]*/){
-             s->dsp.me_cmp[2]= zero_cmp;
-         }
-         if((c->avctx->me_sub_cmp&FF_CMP_CHROMA) && !s->dsp.me_sub_cmp[2]){
-             s->dsp.me_sub_cmp[2]= zero_cmp;
-         }
 -    if ((c->avctx->me_cmp & FF_CMP_CHROMA) /* && !s->mecc.me_cmp[2] */)
 -        s->mecc.me_cmp[2] = zero_cmp;
 -    if ((c->avctx->me_sub_cmp & FF_CMP_CHROMA) && !s->mecc.me_sub_cmp[2])
 -        s->mecc.me_sub_cmp[2] = zero_cmp;
 -    c->hpel_put[2][0]= c->hpel_put[2][1]=
 -    c->hpel_put[2][2]= c->hpel_put[2][3]= zero_hpel;
++    if (s->codec_id != AV_CODEC_ID_SNOW) {
++        if ((c->avctx->me_cmp & FF_CMP_CHROMA) /* && !s->mecc.me_cmp[2] */)
++            s->mecc.me_cmp[2] = zero_cmp;
++        if ((c->avctx->me_sub_cmp & FF_CMP_CHROMA) && !s->mecc.me_sub_cmp[2])
++            s->mecc.me_sub_cmp[2] = zero_cmp;
 +        c->hpel_put[2][0]= c->hpel_put[2][1]=
 +        c->hpel_put[2][2]= c->hpel_put[2][3]= zero_hpel;
 +    }
  
      if(s->codec_id == AV_CODEC_ID_H261){
          c->sub_motion_search= no_sub_motion_search;
@@@ -178,9 -178,12 +177,9 @@@ static inline int get_mb_score(MpegEncC
  
   //FIXME factorize
  
-     cmp_sub= s->dsp.mb_cmp[size];
-     chroma_cmp_sub= s->dsp.mb_cmp[size+1];
+     cmp_sub        = s->mecc.mb_cmp[size];
+     chroma_cmp_sub = s->mecc.mb_cmp[size + 1];
  
 -//    assert(!c->skip);
 -//    assert(c->avctx->me_sub_cmp != c->avctx->mb_cmp);
 -
      d= cmp(s, mx>>(qpel+1), my>>(qpel+1), mx&mask, my&mask, size, h, ref_index, src_index, cmp_sub, chroma_cmp_sub, flags);
      //FIXME check cbp before adding penalty for (0,0) vector
      if(add_rate && (mx || my || size>0))
@@@ -690,10 -693,8 +689,10 @@@ static int sab_diamond_search(MpegEncCo
      LOAD_COMMON2
      unsigned map_generation = c->map_generation;
  
-     cmpf= s->dsp.me_cmp[size];
-     chroma_cmpf= s->dsp.me_cmp[size+1];
 +    av_assert1(minima_count <= MAX_SAB_SIZE);
 +
+     cmpf        = s->mecc.me_cmp[size];
+     chroma_cmpf = s->mecc.me_cmp[size + 1];
  
      /*Note j<MAX_SAB_SIZE is needed if MAX_SAB_SIZE < ME_MAP_SIZE as j can
        become larger due to MVs overflowing their ME_MAP_MV_BITS bits space in map
@@@ -685,21 -689,7 +685,21 @@@ void ff_mpeg4_encode_mb(MpegEncContext 
                          b_pic = pic->f->data[0] + offset;
                          if (!pic->shared)
                              b_pic += INPLACE_OFFSET;
 -                        diff = s->mecc.sad[0](NULL, p_pic, b_pic, s->linesize, 16);
 +
 +                        if (x + 16 > s->width || y + 16 > s->height) {
 +                            int x1, y1;
 +                            int xe = FFMIN(16, s->width - x);
 +                            int ye = FFMIN(16, s->height - y);
 +                            diff = 0;
 +                            for (y1 = 0; y1 < ye; y1++) {
 +                                for (x1 = 0; x1 < xe; x1++) {
 +                                    diff += FFABS(p_pic[x1 + y1 * s->linesize] - b_pic[x1 + y1 * s->linesize]);
 +                                }
 +                            }
 +                            diff = diff * 256 / (xe * ye);
 +                        } else {
-                             diff = s->dsp.sad[0](NULL, p_pic, b_pic, s->linesize, 16);
++                            diff = s->mecc.sad[0](NULL, p_pic, b_pic, s->linesize, 16);
 +                        }
                          if (diff > s->qscale * 70) {  // FIXME check that 70 is optimal
                              s->mb_skipped = 0;
                              break;
@@@ -380,10 -378,9 +380,10 @@@ static void gray8(uint8_t *dst, const u
  av_cold int ff_dct_common_init(MpegEncContext *s)
  {
      ff_blockdsp_init(&s->bdsp, s->avctx);
-     ff_dsputil_init(&s->dsp, s->avctx);
 +    ff_h264chroma_init(&s->h264chroma, 8); //for lowres
      ff_hpeldsp_init(&s->hdsp, s->avctx->flags);
      ff_idctdsp_init(&s->idsp, s->avctx);
+     ff_me_cmp_init(&s->mecc, s->avctx);
      ff_mpegvideodsp_init(&s->mdsp);
      ff_videodsp_init(&s->vdsp, s->avctx->bits_per_raw_sample);
  
@@@ -365,11 -356,10 +365,11 @@@ typedef struct MpegEncContext 
      int h263_long_vectors;      ///< use horrible h263v1 long vector mode
  
      BlockDSPContext bdsp;
-     DSPContext dsp;             ///< pointers for accelerated dsp functions
      FDCTDSPContext fdsp;
 +    H264ChromaContext h264chroma;
      HpelDSPContext hdsp;
      IDCTDSPContext idsp;
+     MECmpContext mecc;
      MpegVideoDSPContext mdsp;
      MpegvideoEncDSPContext mpvencdsp;
      PixblockDSPContext pdsp;
@@@ -835,7 -698,11 +835,8 @@@ av_cold int ff_MPV_encode_init(AVCodecC
      if (ff_MPV_common_init(s) < 0)
          return -1;
  
 -    if (ARCH_X86)
 -        ff_MPV_encode_init_x86(s);
 -
      ff_fdctdsp_init(&s->fdsp, avctx);
+     ff_me_cmp_init(&s->mecc, avctx);
      ff_mpegvideoencdsp_init(&s->mpvencdsp, avctx);
      ff_pixblockdsp_init(&s->pdsp, avctx);
      ff_qpeldsp_init(&s->qdsp);
@@@ -1205,14 -1054,14 +1206,14 @@@ static int skip_check(MpegEncContext *s
                  int off = p->shared ? 0 : 16;
                  uint8_t *dptr = p->f->data[plane] + 8 * (x + y * stride) + off;
                  uint8_t *rptr = ref->f->data[plane] + 8 * (x + y * stride);
-                 int v   = s->dsp.frame_skip_cmp[1](s, dptr, rptr, stride, 8);
+                 int v = s->mecc.frame_skip_cmp[1](s, dptr, rptr, stride, 8);
  
 -                switch (s->avctx->frame_skip_exp) {
 +                switch (FFABS(s->avctx->frame_skip_exp)) {
                  case 0: score    =  FFMAX(score, v);          break;
                  case 1: score   += FFABS(v);                  break;
 -                case 2: score   += v * v;                     break;
 -                case 3: score64 += FFABS(v * v * (int64_t)v); break;
 -                case 4: score64 += v * v * (int64_t)(v * v);  break;
 +                case 2: score64 += v * (int64_t)v;                       break;
 +                case 3: score64 += FFABS(v * (int64_t)v * v);            break;
 +                case 4: score64 += (v * (int64_t)v) * (v * (int64_t)v);  break;
                  }
              }
          }
@@@ -2223,33 -2046,28 +2220,28 @@@ static av_always_inline void encode_mb_
          if (s->current_picture.mc_mb_var[s->mb_stride * mb_y + mb_x] <
                  2 * s->qscale * s->qscale) {
              // FIXME optimize
-             if (s->dsp.sad[1](NULL, ptr_y , dest_y,
-                               wrap_y, 8) < 20 * s->qscale)
+             if (s->mecc.sad[1](NULL, ptr_y, dest_y, wrap_y, 8) < 20 * s->qscale)
                  skip_dct[0] = 1;
-             if (s->dsp.sad[1](NULL, ptr_y + 8,
-                               dest_y + 8, wrap_y, 8) < 20 * s->qscale)
+             if (s->mecc.sad[1](NULL, ptr_y + 8, dest_y + 8, wrap_y, 8) < 20 * s->qscale)
                  skip_dct[1] = 1;
-             if (s->dsp.sad[1](NULL, ptr_y + dct_offset,
-                               dest_y + dct_offset, wrap_y, 8) < 20 * s->qscale)
+             if (s->mecc.sad[1](NULL, ptr_y + dct_offset, dest_y + dct_offset,
+                                wrap_y, 8) < 20 * s->qscale)
                  skip_dct[2] = 1;
-             if (s->dsp.sad[1](NULL, ptr_y + dct_offset + 8,
-                               dest_y + dct_offset + 8,
-                               wrap_y, 8) < 20 * s->qscale)
+             if (s->mecc.sad[1](NULL, ptr_y + dct_offset + 8, dest_y + dct_offset + 8,
+                                wrap_y, 8) < 20 * s->qscale)
                  skip_dct[3] = 1;
-             if (s->dsp.sad[1](NULL, ptr_cb, dest_cb,
-                               wrap_c, 8) < 20 * s->qscale)
+             if (s->mecc.sad[1](NULL, ptr_cb, dest_cb, wrap_c, 8) < 20 * s->qscale)
                  skip_dct[4] = 1;
-             if (s->dsp.sad[1](NULL, ptr_cr, dest_cr,
-                               wrap_c, 8) < 20 * s->qscale)
+             if (s->mecc.sad[1](NULL, ptr_cr, dest_cr, wrap_c, 8) < 20 * s->qscale)
                  skip_dct[5] = 1;
              if (!s->chroma_y_shift) { /* 422 */
-                 if (s->dsp.sad[1](NULL, ptr_cb + uv_dct_offset,
-                                   dest_cb + uv_dct_offset,
-                                   wrap_c, 8) < 20 * s->qscale)
 -                if (s->mecc.sad[1](NULL, ptr_cb + (dct_offset >> 1),
 -                                   dest_cb + (dct_offset >> 1),
++                if (s->mecc.sad[1](NULL, ptr_cb + uv_dct_offset,
++                                   dest_cb + uv_dct_offset,
+                                    wrap_c, 8) < 20 * s->qscale)
                      skip_dct[6] = 1;
-                 if (s->dsp.sad[1](NULL, ptr_cr + uv_dct_offset,
-                                   dest_cr + uv_dct_offset,
-                                   wrap_c, 8) < 20 * s->qscale)
 -                if (s->mecc.sad[1](NULL, ptr_cr + (dct_offset >> 1),
 -                                   dest_cr + (dct_offset >> 1),
++                if (s->mecc.sad[1](NULL, ptr_cr + uv_dct_offset,
++                                   dest_cr + uv_dct_offset,
+                                    wrap_c, 8) < 20 * s->qscale)
                      skip_dct[7] = 1;
              }
          }
Simple merge
@@@ -2,10 -2,9 +2,9 @@@ OBJS                                   
  
  OBJS-$(CONFIG_AUDIODSP)                += ppc/audiodsp.o
  OBJS-$(CONFIG_BLOCKDSP)                += ppc/blockdsp.o
- OBJS-$(CONFIG_DSPUTIL)                 += ppc/dsputil_altivec.o
  OBJS-$(CONFIG_FFT)                     += ppc/fft_altivec.o
  OBJS-$(CONFIG_H264CHROMA)              += ppc/h264chroma_init.o
 -OBJS-$(CONFIG_H264DSP)                 += ppc/h264dsp.o
 +OBJS-$(CONFIG_H264DSP)                 += ppc/h264dsp.o ppc/hpeldsp_altivec.o
  OBJS-$(CONFIG_H264QPEL)                += ppc/h264qpel.o
  OBJS-$(CONFIG_HPELDSP)                 += ppc/hpeldsp_altivec.o
  OBJS-$(CONFIG_HUFFYUVDSP)              += ppc/huffyuvdsp_altivec.o
Simple merge
index cb72979,0000000..14ede5d
mode 100644,000000..100644
--- /dev/null
@@@ -1,57 -1,0 +1,55 @@@
- #include "dsputil.h"
 +/*
 + * Copyright (c) 2010-2011 Maxim Poliakovski
 + * Copyright (c) 2010-2011 Elvis Presley
 + *
 + * 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
 + */
 +
 +#ifndef AVCODEC_PRORESDEC_H
 +#define AVCODEC_PRORESDEC_H
 +
-     DSPContext dsp;
 +#include "blockdsp.h"
 +#include "proresdsp.h"
 +
 +typedef struct {
 +    const uint8_t *data;
 +    unsigned mb_x;
 +    unsigned mb_y;
 +    unsigned mb_count;
 +    unsigned data_size;
 +    int ret;
 +} SliceContext;
 +
 +typedef struct {
 +    BlockDSPContext bdsp;
 +    ProresDSPContext prodsp;
 +    AVFrame *frame;
 +    int frame_type;              ///< 0 = progressive, 1 = tff, 2 = bff
 +    uint8_t qmat_luma[64];
 +    uint8_t qmat_chroma[64];
 +    SliceContext *slices;
 +    int slice_count;             ///< number of slices in the current picture
 +    unsigned mb_width;           ///< width of the current picture in mb
 +    unsigned mb_height;          ///< height of the current picture in mb
 +    uint8_t progressive_scan[64];
 +    uint8_t interlaced_scan[64];
 +    const uint8_t *scan;
 +    int first_field;
 +    int alpha_info;
 +} ProresContext;
 +
 +#endif /* AVCODEC_PRORESDEC_H */
index d597114,0000000..4d04a0a
mode 100644,000000..100644
--- /dev/null
@@@ -1,690 -1,0 +1,689 @@@
-     ff_dsputil_init(&ctx->dsp, avctx);
 +/*
 + * Copyright (c) 2010-2011 Maxim Poliakovski
 + * Copyright (c) 2010-2011 Elvis Presley
 + *
 + * 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
 + */
 +
 +/**
 + * @file
 + * Known FOURCCs: 'apch' (HQ), 'apcn' (SD), 'apcs' (LT), 'acpo' (Proxy), 'ap4h' (4444)
 + */
 +
 +//#define DEBUG
 +
 +#define LONG_BITSTREAM_READER
 +
 +#include "avcodec.h"
 +#include "get_bits.h"
 +#include "idctdsp.h"
 +#include "internal.h"
 +#include "simple_idct.h"
 +#include "proresdec.h"
 +#include "proresdata.h"
 +
 +static void permute(uint8_t *dst, const uint8_t *src, const uint8_t permutation[64])
 +{
 +    int i;
 +    for (i = 0; i < 64; i++)
 +        dst[i] = permutation[src[i]];
 +}
 +
 +static av_cold int decode_init(AVCodecContext *avctx)
 +{
 +    ProresContext *ctx = avctx->priv_data;
 +    uint8_t idct_permutation[64];
 +
 +    avctx->bits_per_raw_sample = 10;
 +
 +    ff_blockdsp_init(&ctx->bdsp, avctx);
 +    ff_proresdsp_init(&ctx->prodsp, avctx);
 +
 +    ff_init_scantable_permutation(idct_permutation,
 +                                  ctx->prodsp.idct_permutation_type);
 +
 +    permute(ctx->progressive_scan, ff_prores_progressive_scan, idct_permutation);
 +    permute(ctx->interlaced_scan, ff_prores_interlaced_scan, idct_permutation);
 +
 +    return 0;
 +}
 +
 +static int decode_frame_header(ProresContext *ctx, const uint8_t *buf,
 +                               const int data_size, AVCodecContext *avctx)
 +{
 +    int hdr_size, width, height, flags;
 +    int version;
 +    const uint8_t *ptr;
 +
 +    hdr_size = AV_RB16(buf);
 +    av_dlog(avctx, "header size %d\n", hdr_size);
 +    if (hdr_size > data_size) {
 +        av_log(avctx, AV_LOG_ERROR, "error, wrong header size\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    version = AV_RB16(buf + 2);
 +    av_dlog(avctx, "%.4s version %d\n", buf+4, version);
 +    if (version > 1) {
 +        av_log(avctx, AV_LOG_ERROR, "unsupported version: %d\n", version);
 +        return AVERROR_PATCHWELCOME;
 +    }
 +
 +    width  = AV_RB16(buf + 8);
 +    height = AV_RB16(buf + 10);
 +    if (width != avctx->width || height != avctx->height) {
 +        av_log(avctx, AV_LOG_ERROR, "picture resolution change: %dx%d -> %dx%d\n",
 +               avctx->width, avctx->height, width, height);
 +        return AVERROR_PATCHWELCOME;
 +    }
 +
 +    ctx->frame_type = (buf[12] >> 2) & 3;
 +    ctx->alpha_info = buf[17] & 0xf;
 +
 +    if (ctx->alpha_info > 2) {
 +        av_log(avctx, AV_LOG_ERROR, "Invalid alpha mode %d\n", ctx->alpha_info);
 +        return AVERROR_INVALIDDATA;
 +    }
 +    if (avctx->skip_alpha) ctx->alpha_info = 0;
 +
 +    av_dlog(avctx, "frame type %d\n", ctx->frame_type);
 +
 +    if (ctx->frame_type == 0) {
 +        ctx->scan = ctx->progressive_scan; // permuted
 +    } else {
 +        ctx->scan = ctx->interlaced_scan; // permuted
 +        ctx->frame->interlaced_frame = 1;
 +        ctx->frame->top_field_first = ctx->frame_type == 1;
 +    }
 +
 +    if (ctx->alpha_info) {
 +        avctx->pix_fmt = (buf[12] & 0xC0) == 0xC0 ? AV_PIX_FMT_YUVA444P10 : AV_PIX_FMT_YUVA422P10;
 +    } else {
 +        avctx->pix_fmt = (buf[12] & 0xC0) == 0xC0 ? AV_PIX_FMT_YUV444P10 : AV_PIX_FMT_YUV422P10;
 +    }
 +
 +    ptr   = buf + 20;
 +    flags = buf[19];
 +    av_dlog(avctx, "flags %x\n", flags);
 +
 +    if (flags & 2) {
 +        if(buf + data_size - ptr < 64) {
 +            av_log(avctx, AV_LOG_ERROR, "Header truncated\n");
 +            return AVERROR_INVALIDDATA;
 +        }
 +        permute(ctx->qmat_luma, ctx->prodsp.idct_permutation, ptr);
 +        ptr += 64;
 +    } else {
 +        memset(ctx->qmat_luma, 4, 64);
 +    }
 +
 +    if (flags & 1) {
 +        if(buf + data_size - ptr < 64) {
 +            av_log(avctx, AV_LOG_ERROR, "Header truncated\n");
 +            return AVERROR_INVALIDDATA;
 +        }
 +        permute(ctx->qmat_chroma, ctx->prodsp.idct_permutation, ptr);
 +    } else {
 +        memset(ctx->qmat_chroma, 4, 64);
 +    }
 +
 +    return hdr_size;
 +}
 +
 +static int decode_picture_header(AVCodecContext *avctx, const uint8_t *buf, const int buf_size)
 +{
 +    ProresContext *ctx = avctx->priv_data;
 +    int i, hdr_size, slice_count;
 +    unsigned pic_data_size;
 +    int log2_slice_mb_width, log2_slice_mb_height;
 +    int slice_mb_count, mb_x, mb_y;
 +    const uint8_t *data_ptr, *index_ptr;
 +
 +    hdr_size = buf[0] >> 3;
 +    if (hdr_size < 8 || hdr_size > buf_size) {
 +        av_log(avctx, AV_LOG_ERROR, "error, wrong picture header size\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    pic_data_size = AV_RB32(buf + 1);
 +    if (pic_data_size > buf_size) {
 +        av_log(avctx, AV_LOG_ERROR, "error, wrong picture data size\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    log2_slice_mb_width  = buf[7] >> 4;
 +    log2_slice_mb_height = buf[7] & 0xF;
 +    if (log2_slice_mb_width > 3 || log2_slice_mb_height) {
 +        av_log(avctx, AV_LOG_ERROR, "unsupported slice resolution: %dx%d\n",
 +               1 << log2_slice_mb_width, 1 << log2_slice_mb_height);
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    ctx->mb_width  = (avctx->width  + 15) >> 4;
 +    if (ctx->frame_type)
 +        ctx->mb_height = (avctx->height + 31) >> 5;
 +    else
 +        ctx->mb_height = (avctx->height + 15) >> 4;
 +
 +    slice_count = AV_RB16(buf + 5);
 +
 +    if (ctx->slice_count != slice_count || !ctx->slices) {
 +        av_freep(&ctx->slices);
 +        ctx->slices = av_mallocz_array(slice_count, sizeof(*ctx->slices));
 +        if (!ctx->slices)
 +            return AVERROR(ENOMEM);
 +        ctx->slice_count = slice_count;
 +    }
 +
 +    if (!slice_count)
 +        return AVERROR(EINVAL);
 +
 +    if (hdr_size + slice_count*2 > buf_size) {
 +        av_log(avctx, AV_LOG_ERROR, "error, wrong slice count\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    // parse slice information
 +    index_ptr = buf + hdr_size;
 +    data_ptr  = index_ptr + slice_count*2;
 +
 +    slice_mb_count = 1 << log2_slice_mb_width;
 +    mb_x = 0;
 +    mb_y = 0;
 +
 +    for (i = 0; i < slice_count; i++) {
 +        SliceContext *slice = &ctx->slices[i];
 +
 +        slice->data = data_ptr;
 +        data_ptr += AV_RB16(index_ptr + i*2);
 +
 +        while (ctx->mb_width - mb_x < slice_mb_count)
 +            slice_mb_count >>= 1;
 +
 +        slice->mb_x = mb_x;
 +        slice->mb_y = mb_y;
 +        slice->mb_count = slice_mb_count;
 +        slice->data_size = data_ptr - slice->data;
 +
 +        if (slice->data_size < 6) {
 +            av_log(avctx, AV_LOG_ERROR, "error, wrong slice data size\n");
 +            return AVERROR_INVALIDDATA;
 +        }
 +
 +        mb_x += slice_mb_count;
 +        if (mb_x == ctx->mb_width) {
 +            slice_mb_count = 1 << log2_slice_mb_width;
 +            mb_x = 0;
 +            mb_y++;
 +        }
 +        if (data_ptr > buf + buf_size) {
 +            av_log(avctx, AV_LOG_ERROR, "error, slice out of bounds\n");
 +            return AVERROR_INVALIDDATA;
 +        }
 +    }
 +
 +    if (mb_x || mb_y != ctx->mb_height) {
 +        av_log(avctx, AV_LOG_ERROR, "error wrong mb count y %d h %d\n",
 +               mb_y, ctx->mb_height);
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    return pic_data_size;
 +}
 +
 +#define DECODE_CODEWORD(val, codebook)                                  \
 +    do {                                                                \
 +        unsigned int rice_order, exp_order, switch_bits;                \
 +        unsigned int q, buf, bits;                                      \
 +                                                                        \
 +        UPDATE_CACHE(re, gb);                                           \
 +        buf = GET_CACHE(re, gb);                                        \
 +                                                                        \
 +        /* number of bits to switch between rice and exp golomb */      \
 +        switch_bits =  codebook & 3;                                    \
 +        rice_order  =  codebook >> 5;                                   \
 +        exp_order   = (codebook >> 2) & 7;                              \
 +                                                                        \
 +        q = 31 - av_log2(buf);                                          \
 +                                                                        \
 +        if (q > switch_bits) { /* exp golomb */                         \
 +            bits = exp_order - switch_bits + (q<<1);                    \
 +            val = SHOW_UBITS(re, gb, bits) - (1 << exp_order) +         \
 +                ((switch_bits + 1) << rice_order);                      \
 +            SKIP_BITS(re, gb, bits);                                    \
 +        } else if (rice_order) {                                        \
 +            SKIP_BITS(re, gb, q+1);                                     \
 +            val = (q << rice_order) + SHOW_UBITS(re, gb, rice_order);   \
 +            SKIP_BITS(re, gb, rice_order);                              \
 +        } else {                                                        \
 +            val = q;                                                    \
 +            SKIP_BITS(re, gb, q+1);                                     \
 +        }                                                               \
 +    } while (0)
 +
 +#define TOSIGNED(x) (((x) >> 1) ^ (-((x) & 1)))
 +
 +#define FIRST_DC_CB 0xB8
 +
 +static const uint8_t dc_codebook[7] = { 0x04, 0x28, 0x28, 0x4D, 0x4D, 0x70, 0x70};
 +
 +static av_always_inline void decode_dc_coeffs(GetBitContext *gb, int16_t *out,
 +                                              int blocks_per_slice)
 +{
 +    int16_t prev_dc;
 +    int code, i, sign;
 +
 +    OPEN_READER(re, gb);
 +
 +    DECODE_CODEWORD(code, FIRST_DC_CB);
 +    prev_dc = TOSIGNED(code);
 +    out[0] = prev_dc;
 +
 +    out += 64; // dc coeff for the next block
 +
 +    code = 5;
 +    sign = 0;
 +    for (i = 1; i < blocks_per_slice; i++, out += 64) {
 +        DECODE_CODEWORD(code, dc_codebook[FFMIN(code, 6U)]);
 +        if(code) sign ^= -(code & 1);
 +        else     sign  = 0;
 +        prev_dc += (((code + 1) >> 1) ^ sign) - sign;
 +        out[0] = prev_dc;
 +    }
 +    CLOSE_READER(re, gb);
 +}
 +
 +// adaptive codebook switching lut according to previous run/level values
 +static const uint8_t run_to_cb[16] = { 0x06, 0x06, 0x05, 0x05, 0x04, 0x29, 0x29, 0x29, 0x29, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x4C };
 +static const uint8_t lev_to_cb[10] = { 0x04, 0x0A, 0x05, 0x06, 0x04, 0x28, 0x28, 0x28, 0x28, 0x4C };
 +
 +static av_always_inline int decode_ac_coeffs(AVCodecContext *avctx, GetBitContext *gb,
 +                                             int16_t *out, int blocks_per_slice)
 +{
 +    ProresContext *ctx = avctx->priv_data;
 +    int block_mask, sign;
 +    unsigned pos, run, level;
 +    int max_coeffs, i, bits_left;
 +    int log2_block_count = av_log2(blocks_per_slice);
 +
 +    OPEN_READER(re, gb);
 +    UPDATE_CACHE(re, gb);                                           \
 +    run   = 4;
 +    level = 2;
 +
 +    max_coeffs = 64 << log2_block_count;
 +    block_mask = blocks_per_slice - 1;
 +
 +    for (pos = block_mask;;) {
 +        bits_left = gb->size_in_bits - re_index;
 +        if (!bits_left || (bits_left < 32 && !SHOW_UBITS(re, gb, bits_left)))
 +            break;
 +
 +        DECODE_CODEWORD(run, run_to_cb[FFMIN(run,  15)]);
 +        pos += run + 1;
 +        if (pos >= max_coeffs) {
 +            av_log(avctx, AV_LOG_ERROR, "ac tex damaged %d, %d\n", pos, max_coeffs);
 +            return AVERROR_INVALIDDATA;
 +        }
 +
 +        DECODE_CODEWORD(level, lev_to_cb[FFMIN(level, 9)]);
 +        level += 1;
 +
 +        i = pos >> log2_block_count;
 +
 +        sign = SHOW_SBITS(re, gb, 1);
 +        SKIP_BITS(re, gb, 1);
 +        out[((pos & block_mask) << 6) + ctx->scan[i]] = ((level ^ sign) - sign);
 +    }
 +
 +    CLOSE_READER(re, gb);
 +    return 0;
 +}
 +
 +static int decode_slice_luma(AVCodecContext *avctx, SliceContext *slice,
 +                             uint16_t *dst, int dst_stride,
 +                             const uint8_t *buf, unsigned buf_size,
 +                             const int16_t *qmat)
 +{
 +    ProresContext *ctx = avctx->priv_data;
 +    LOCAL_ALIGNED_16(int16_t, blocks, [8*4*64]);
 +    int16_t *block;
 +    GetBitContext gb;
 +    int i, blocks_per_slice = slice->mb_count<<2;
 +    int ret;
 +
 +    for (i = 0; i < blocks_per_slice; i++)
 +        ctx->bdsp.clear_block(blocks+(i<<6));
 +
 +    init_get_bits(&gb, buf, buf_size << 3);
 +
 +    decode_dc_coeffs(&gb, blocks, blocks_per_slice);
 +    if ((ret = decode_ac_coeffs(avctx, &gb, blocks, blocks_per_slice)) < 0)
 +        return ret;
 +
 +    block = blocks;
 +    for (i = 0; i < slice->mb_count; i++) {
 +        ctx->prodsp.idct_put(dst, dst_stride, block+(0<<6), qmat);
 +        ctx->prodsp.idct_put(dst             +8, dst_stride, block+(1<<6), qmat);
 +        ctx->prodsp.idct_put(dst+4*dst_stride  , dst_stride, block+(2<<6), qmat);
 +        ctx->prodsp.idct_put(dst+4*dst_stride+8, dst_stride, block+(3<<6), qmat);
 +        block += 4*64;
 +        dst += 16;
 +    }
 +    return 0;
 +}
 +
 +static int decode_slice_chroma(AVCodecContext *avctx, SliceContext *slice,
 +                               uint16_t *dst, int dst_stride,
 +                               const uint8_t *buf, unsigned buf_size,
 +                               const int16_t *qmat, int log2_blocks_per_mb)
 +{
 +    ProresContext *ctx = avctx->priv_data;
 +    LOCAL_ALIGNED_16(int16_t, blocks, [8*4*64]);
 +    int16_t *block;
 +    GetBitContext gb;
 +    int i, j, blocks_per_slice = slice->mb_count << log2_blocks_per_mb;
 +    int ret;
 +
 +    for (i = 0; i < blocks_per_slice; i++)
 +        ctx->bdsp.clear_block(blocks+(i<<6));
 +
 +    init_get_bits(&gb, buf, buf_size << 3);
 +
 +    decode_dc_coeffs(&gb, blocks, blocks_per_slice);
 +    if ((ret = decode_ac_coeffs(avctx, &gb, blocks, blocks_per_slice)) < 0)
 +        return ret;
 +
 +    block = blocks;
 +    for (i = 0; i < slice->mb_count; i++) {
 +        for (j = 0; j < log2_blocks_per_mb; j++) {
 +            ctx->prodsp.idct_put(dst,              dst_stride, block+(0<<6), qmat);
 +            ctx->prodsp.idct_put(dst+4*dst_stride, dst_stride, block+(1<<6), qmat);
 +            block += 2*64;
 +            dst += 8;
 +        }
 +    }
 +    return 0;
 +}
 +
 +static void unpack_alpha(GetBitContext *gb, uint16_t *dst, int num_coeffs,
 +                         const int num_bits)
 +{
 +    const int mask = (1 << num_bits) - 1;
 +    int i, idx, val, alpha_val;
 +
 +    idx       = 0;
 +    alpha_val = mask;
 +    do {
 +        do {
 +            if (get_bits1(gb)) {
 +                val = get_bits(gb, num_bits);
 +            } else {
 +                int sign;
 +                val  = get_bits(gb, num_bits == 16 ? 7 : 4);
 +                sign = val & 1;
 +                val  = (val + 2) >> 1;
 +                if (sign)
 +                    val = -val;
 +            }
 +            alpha_val = (alpha_val + val) & mask;
 +            if (num_bits == 16) {
 +                dst[idx++] = alpha_val >> 6;
 +            } else {
 +                dst[idx++] = (alpha_val << 2) | (alpha_val >> 6);
 +            }
 +            if (idx >= num_coeffs)
 +                break;
 +        } while (get_bits_left(gb)>0 && get_bits1(gb));
 +        val = get_bits(gb, 4);
 +        if (!val)
 +            val = get_bits(gb, 11);
 +        if (idx + val > num_coeffs)
 +            val = num_coeffs - idx;
 +        if (num_bits == 16) {
 +            for (i = 0; i < val; i++)
 +                dst[idx++] = alpha_val >> 6;
 +        } else {
 +            for (i = 0; i < val; i++)
 +                dst[idx++] = (alpha_val << 2) | (alpha_val >> 6);
 +
 +        }
 +    } while (idx < num_coeffs);
 +}
 +
 +/**
 + * Decode alpha slice plane.
 + */
 +static void decode_slice_alpha(ProresContext *ctx,
 +                               uint16_t *dst, int dst_stride,
 +                               const uint8_t *buf, int buf_size,
 +                               int blocks_per_slice)
 +{
 +    GetBitContext gb;
 +    int i;
 +    LOCAL_ALIGNED_16(int16_t, blocks, [8*4*64]);
 +    int16_t *block;
 +
 +    for (i = 0; i < blocks_per_slice<<2; i++)
 +        ctx->bdsp.clear_block(blocks+(i<<6));
 +
 +    init_get_bits(&gb, buf, buf_size << 3);
 +
 +    if (ctx->alpha_info == 2) {
 +        unpack_alpha(&gb, blocks, blocks_per_slice * 4 * 64, 16);
 +    } else {
 +        unpack_alpha(&gb, blocks, blocks_per_slice * 4 * 64, 8);
 +    }
 +
 +    block = blocks;
 +    for (i = 0; i < 16; i++) {
 +        memcpy(dst, block, 16 * blocks_per_slice * sizeof(*dst));
 +        dst   += dst_stride >> 1;
 +        block += 16 * blocks_per_slice;
 +    }
 +}
 +
 +static int decode_slice_thread(AVCodecContext *avctx, void *arg, int jobnr, int threadnr)
 +{
 +    ProresContext *ctx = avctx->priv_data;
 +    SliceContext *slice = &ctx->slices[jobnr];
 +    const uint8_t *buf = slice->data;
 +    AVFrame *pic = ctx->frame;
 +    int i, hdr_size, qscale, log2_chroma_blocks_per_mb;
 +    int luma_stride, chroma_stride;
 +    int y_data_size, u_data_size, v_data_size, a_data_size;
 +    uint8_t *dest_y, *dest_u, *dest_v, *dest_a;
 +    int16_t qmat_luma_scaled[64];
 +    int16_t qmat_chroma_scaled[64];
 +    int mb_x_shift;
 +    int ret;
 +
 +    slice->ret = -1;
 +    //av_log(avctx, AV_LOG_INFO, "slice %d mb width %d mb x %d y %d\n",
 +    //       jobnr, slice->mb_count, slice->mb_x, slice->mb_y);
 +
 +    // slice header
 +    hdr_size = buf[0] >> 3;
 +    qscale = av_clip(buf[1], 1, 224);
 +    qscale = qscale > 128 ? qscale - 96 << 2: qscale;
 +    y_data_size = AV_RB16(buf + 2);
 +    u_data_size = AV_RB16(buf + 4);
 +    v_data_size = slice->data_size - y_data_size - u_data_size - hdr_size;
 +    if (hdr_size > 7) v_data_size = AV_RB16(buf + 6);
 +    a_data_size = slice->data_size - y_data_size - u_data_size -
 +                  v_data_size - hdr_size;
 +
 +    if (y_data_size < 0 || u_data_size < 0 || v_data_size < 0
 +        || hdr_size+y_data_size+u_data_size+v_data_size > slice->data_size){
 +        av_log(avctx, AV_LOG_ERROR, "invalid plane data size\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    buf += hdr_size;
 +
 +    for (i = 0; i < 64; i++) {
 +        qmat_luma_scaled  [i] = ctx->qmat_luma  [i] * qscale;
 +        qmat_chroma_scaled[i] = ctx->qmat_chroma[i] * qscale;
 +    }
 +
 +    if (ctx->frame_type == 0) {
 +        luma_stride   = pic->linesize[0];
 +        chroma_stride = pic->linesize[1];
 +    } else {
 +        luma_stride   = pic->linesize[0] << 1;
 +        chroma_stride = pic->linesize[1] << 1;
 +    }
 +
 +    if (avctx->pix_fmt == AV_PIX_FMT_YUV444P10 || avctx->pix_fmt == AV_PIX_FMT_YUVA444P10) {
 +        mb_x_shift = 5;
 +        log2_chroma_blocks_per_mb = 2;
 +    } else {
 +        mb_x_shift = 4;
 +        log2_chroma_blocks_per_mb = 1;
 +    }
 +
 +    dest_y = pic->data[0] + (slice->mb_y << 4) * luma_stride + (slice->mb_x << 5);
 +    dest_u = pic->data[1] + (slice->mb_y << 4) * chroma_stride + (slice->mb_x << mb_x_shift);
 +    dest_v = pic->data[2] + (slice->mb_y << 4) * chroma_stride + (slice->mb_x << mb_x_shift);
 +    dest_a = pic->data[3] + (slice->mb_y << 4) * luma_stride + (slice->mb_x << 5);
 +
 +    if (ctx->frame_type && ctx->first_field ^ ctx->frame->top_field_first) {
 +        dest_y += pic->linesize[0];
 +        dest_u += pic->linesize[1];
 +        dest_v += pic->linesize[2];
 +        dest_a += pic->linesize[3];
 +    }
 +
 +    ret = decode_slice_luma(avctx, slice, (uint16_t*)dest_y, luma_stride,
 +                            buf, y_data_size, qmat_luma_scaled);
 +    if (ret < 0)
 +        return ret;
 +
 +    if (!(avctx->flags & CODEC_FLAG_GRAY)) {
 +        ret = decode_slice_chroma(avctx, slice, (uint16_t*)dest_u, chroma_stride,
 +                                  buf + y_data_size, u_data_size,
 +                                  qmat_chroma_scaled, log2_chroma_blocks_per_mb);
 +        if (ret < 0)
 +            return ret;
 +
 +        ret = decode_slice_chroma(avctx, slice, (uint16_t*)dest_v, chroma_stride,
 +                                  buf + y_data_size + u_data_size, v_data_size,
 +                                  qmat_chroma_scaled, log2_chroma_blocks_per_mb);
 +        if (ret < 0)
 +            return ret;
 +    }
 +    /* decode alpha plane if available */
 +    if (ctx->alpha_info && pic->data[3] && a_data_size)
 +        decode_slice_alpha(ctx, (uint16_t*)dest_a, luma_stride,
 +                           buf + y_data_size + u_data_size + v_data_size,
 +                           a_data_size, slice->mb_count);
 +
 +    slice->ret = 0;
 +    return 0;
 +}
 +
 +static int decode_picture(AVCodecContext *avctx)
 +{
 +    ProresContext *ctx = avctx->priv_data;
 +    int i;
 +
 +    avctx->execute2(avctx, decode_slice_thread, NULL, NULL, ctx->slice_count);
 +
 +    for (i = 0; i < ctx->slice_count; i++)
 +        if (ctx->slices[i].ret < 0)
 +            return ctx->slices[i].ret;
 +
 +    return 0;
 +}
 +
 +static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
 +                        AVPacket *avpkt)
 +{
 +    ProresContext *ctx = avctx->priv_data;
 +    AVFrame *frame = data;
 +    const uint8_t *buf = avpkt->data;
 +    int buf_size = avpkt->size;
 +    int frame_hdr_size, pic_size, ret;
 +
 +    if (buf_size < 28 || AV_RL32(buf + 4) != AV_RL32("icpf")) {
 +        av_log(avctx, AV_LOG_ERROR, "invalid frame header\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    ctx->frame = frame;
 +    ctx->frame->pict_type = AV_PICTURE_TYPE_I;
 +    ctx->frame->key_frame = 1;
 +    ctx->first_field = 1;
 +
 +    buf += 8;
 +    buf_size -= 8;
 +
 +    frame_hdr_size = decode_frame_header(ctx, buf, buf_size, avctx);
 +    if (frame_hdr_size < 0)
 +        return frame_hdr_size;
 +
 +    buf += frame_hdr_size;
 +    buf_size -= frame_hdr_size;
 +
 +    if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
 +        return ret;
 +
 + decode_picture:
 +    pic_size = decode_picture_header(avctx, buf, buf_size);
 +    if (pic_size < 0) {
 +        av_log(avctx, AV_LOG_ERROR, "error decoding picture header\n");
 +        return pic_size;
 +    }
 +
 +    if ((ret = decode_picture(avctx)) < 0) {
 +        av_log(avctx, AV_LOG_ERROR, "error decoding picture\n");
 +        return ret;
 +    }
 +
 +    buf += pic_size;
 +    buf_size -= pic_size;
 +
 +    if (ctx->frame_type && buf_size > 0 && ctx->first_field) {
 +        ctx->first_field = 0;
 +        goto decode_picture;
 +    }
 +
 +    *got_frame      = 1;
 +
 +    return avpkt->size;
 +}
 +
 +static av_cold int decode_close(AVCodecContext *avctx)
 +{
 +    ProresContext *ctx = avctx->priv_data;
 +
 +    av_freep(&ctx->slices);
 +
 +    return 0;
 +}
 +
 +AVCodec ff_prores_decoder = {
 +    .name           = "prores",
 +    .long_name      = NULL_IF_CONFIG_SMALL("ProRes"),
 +    .type           = AVMEDIA_TYPE_VIDEO,
 +    .id             = AV_CODEC_ID_PRORES,
 +    .priv_data_size = sizeof(ProresContext),
 +    .init           = decode_init,
 +    .close          = decode_close,
 +    .decode         = decode_frame,
 +    .capabilities   = CODEC_CAP_DR1 | CODEC_CAP_SLICE_THREADS,
 +};
Simple merge
index b2445ca,0000000..f471f49
mode 100644,000000..100644
--- /dev/null
@@@ -1,637 -1,0 +1,636 @@@
- #include "dsputil.h"
 +/*
 + * Apple ProRes encoder
 + *
 + * Copyright (c) 2011 Anatoliy Wasserman
 + *
 + * 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
 + */
 +
 +/**
 + * @file
 + * Apple ProRes encoder (Anatoliy Wasserman version)
 + * Known FOURCCs: 'apch' (HQ), 'apcn' (SD), 'apcs' (LT), 'acpo' (Proxy)
 + */
 +
 +#include "avcodec.h"
 +#include "dct.h"
 +#include "internal.h"
 +#include "put_bits.h"
 +#include "bytestream.h"
 +#include "fdctdsp.h"
 +
 +#define DEFAULT_SLICE_MB_WIDTH 8
 +
 +#define FF_PROFILE_PRORES_PROXY     0
 +#define FF_PROFILE_PRORES_LT        1
 +#define FF_PROFILE_PRORES_STANDARD  2
 +#define FF_PROFILE_PRORES_HQ        3
 +
 +static const AVProfile profiles[] = {
 +    { FF_PROFILE_PRORES_PROXY,    "apco"},
 +    { FF_PROFILE_PRORES_LT,       "apcs"},
 +    { FF_PROFILE_PRORES_STANDARD, "apcn"},
 +    { FF_PROFILE_PRORES_HQ,       "apch"},
 +    { FF_PROFILE_UNKNOWN }
 +};
 +
 +static const int qp_start_table[4] = { 4, 1, 1, 1 };
 +static const int qp_end_table[4]   = { 8, 9, 6, 6 };
 +static const int bitrate_table[5]  = { 1000, 2100, 3500, 5400 };
 +
 +static const uint8_t progressive_scan[64] = {
 +     0,  1,  8,  9,  2,  3, 10, 11,
 +    16, 17, 24, 25, 18, 19, 26, 27,
 +     4,  5, 12, 20, 13,  6,  7, 14,
 +    21, 28, 29, 22, 15, 23, 30, 31,
 +    32, 33, 40, 48, 41, 34, 35, 42,
 +    49, 56, 57, 50, 43, 36, 37, 44,
 +    51, 58, 59, 52, 45, 38, 39, 46,
 +    53, 60, 61, 54, 47, 55, 62, 63
 +};
 +
 +static const uint8_t QMAT_LUMA[4][64] = {
 +    {
 +         4,  7,  9, 11, 13, 14, 15, 63,
 +         7,  7, 11, 12, 14, 15, 63, 63,
 +         9, 11, 13, 14, 15, 63, 63, 63,
 +        11, 11, 13, 14, 63, 63, 63, 63,
 +        11, 13, 14, 63, 63, 63, 63, 63,
 +        13, 14, 63, 63, 63, 63, 63, 63,
 +        13, 63, 63, 63, 63, 63, 63, 63,
 +        63, 63, 63, 63, 63, 63, 63, 63
 +    }, {
 +         4,  5,  6,  7,  9, 11, 13, 15,
 +         5,  5,  7,  8, 11, 13, 15, 17,
 +         6,  7,  9, 11, 13, 15, 15, 17,
 +         7,  7,  9, 11, 13, 15, 17, 19,
 +         7,  9, 11, 13, 14, 16, 19, 23,
 +         9, 11, 13, 14, 16, 19, 23, 29,
 +         9, 11, 13, 15, 17, 21, 28, 35,
 +        11, 13, 16, 17, 21, 28, 35, 41
 +    }, {
 +         4,  4,  5,  5,  6,  7,  7,  9,
 +         4,  4,  5,  6,  7,  7,  9,  9,
 +         5,  5,  6,  7,  7,  9,  9, 10,
 +         5,  5,  6,  7,  7,  9,  9, 10,
 +         5,  6,  7,  7,  8,  9, 10, 12,
 +         6,  7,  7,  8,  9, 10, 12, 15,
 +         6,  7,  7,  9, 10, 11, 14, 17,
 +         7,  7,  9, 10, 11, 14, 17, 21
 +    }, {
 +         4,  4,  4,  4,  4,  4,  4,  4,
 +         4,  4,  4,  4,  4,  4,  4,  4,
 +         4,  4,  4,  4,  4,  4,  4,  4,
 +         4,  4,  4,  4,  4,  4,  4,  5,
 +         4,  4,  4,  4,  4,  4,  5,  5,
 +         4,  4,  4,  4,  4,  5,  5,  6,
 +         4,  4,  4,  4,  5,  5,  6,  7,
 +         4,  4,  4,  4,  5,  6,  7,  7
 +    }
 +};
 +
 +static const uint8_t QMAT_CHROMA[4][64] = {
 +    {
 +         4,  7,  9, 11, 13, 14, 63, 63,
 +         7,  7, 11, 12, 14, 63, 63, 63,
 +         9, 11, 13, 14, 63, 63, 63, 63,
 +        11, 11, 13, 14, 63, 63, 63, 63,
 +        11, 13, 14, 63, 63, 63, 63, 63,
 +        13, 14, 63, 63, 63, 63, 63, 63,
 +        13, 63, 63, 63, 63, 63, 63, 63,
 +        63, 63, 63, 63, 63, 63, 63, 63
 +    }, {
 +         4,  5,  6,  7,  9, 11, 13, 15,
 +         5,  5,  7,  8, 11, 13, 15, 17,
 +         6,  7,  9, 11, 13, 15, 15, 17,
 +         7,  7,  9, 11, 13, 15, 17, 19,
 +         7,  9, 11, 13, 14, 16, 19, 23,
 +         9, 11, 13, 14, 16, 19, 23, 29,
 +         9, 11, 13, 15, 17, 21, 28, 35,
 +        11, 13, 16, 17, 21, 28, 35, 41
 +    }, {
 +         4,  4,  5,  5,  6,  7,  7,  9,
 +         4,  4,  5,  6,  7,  7,  9,  9,
 +         5,  5,  6,  7,  7,  9,  9, 10,
 +         5,  5,  6,  7,  7,  9,  9, 10,
 +         5,  6,  7,  7,  8,  9, 10, 12,
 +         6,  7,  7,  8,  9, 10, 12, 15,
 +         6,  7,  7,  9, 10, 11, 14, 17,
 +         7,  7,  9, 10, 11, 14, 17, 21
 +    }, {
 +         4,  4,  4,  4,  4,  4,  4,  4,
 +         4,  4,  4,  4,  4,  4,  4,  4,
 +         4,  4,  4,  4,  4,  4,  4,  4,
 +         4,  4,  4,  4,  4,  4,  4,  5,
 +         4,  4,  4,  4,  4,  4,  5,  5,
 +         4,  4,  4,  4,  4,  5,  5,  6,
 +         4,  4,  4,  4,  5,  5,  6,  7,
 +         4,  4,  4,  4,  5,  6,  7,  7
 +    }
 +};
 +
 +
 +typedef struct {
 +    FDCTDSPContext fdsp;
 +    uint8_t* fill_y;
 +    uint8_t* fill_u;
 +    uint8_t* fill_v;
 +
 +    int qmat_luma[16][64];
 +    int qmat_chroma[16][64];
 +} ProresContext;
 +
 +static void encode_codeword(PutBitContext *pb, int val, int codebook)
 +{
 +    unsigned int rice_order, exp_order, switch_bits, first_exp, exp, zeros,
 +            mask;
 +
 +    /* number of bits to switch between rice and exp golomb */
 +    switch_bits = codebook & 3;
 +    rice_order  = codebook >> 5;
 +    exp_order   = (codebook >> 2) & 7;
 +
 +    first_exp = ((switch_bits + 1) << rice_order);
 +
 +    if (val >= first_exp) { /* exp golomb */
 +        val -= first_exp;
 +        val += (1 << exp_order);
 +        exp = av_log2(val);
 +        zeros = exp - exp_order + switch_bits + 1;
 +        put_bits(pb, zeros, 0);
 +        put_bits(pb, exp + 1, val);
 +    } else if (rice_order) {
 +        mask = (1 << rice_order) - 1;
 +        put_bits(pb, (val >> rice_order), 0);
 +        put_bits(pb, 1, 1);
 +        put_bits(pb, rice_order, val & mask);
 +    } else {
 +        put_bits(pb, val, 0);
 +        put_bits(pb, 1, 1);
 +    }
 +}
 +
 +#define QSCALE(qmat,ind,val) ((val) / ((qmat)[ind]))
 +#define TO_GOLOMB(val) (((val) << 1) ^ ((val) >> 31))
 +#define DIFF_SIGN(val, sign) (((val) >> 31) ^ (sign))
 +#define IS_NEGATIVE(val) ((((val) >> 31) ^ -1) + 1)
 +#define TO_GOLOMB2(val,sign) ((val)==0 ? 0 : ((val) << 1) + (sign))
 +
 +static av_always_inline int get_level(int val)
 +{
 +    int sign = (val >> 31);
 +    return (val ^ sign) - sign;
 +}
 +
 +#define FIRST_DC_CB 0xB8
 +
 +static const uint8_t dc_codebook[7] = { 0x04, 0x28, 0x28, 0x4D, 0x4D, 0x70, 0x70};
 +
 +static void encode_dc_coeffs(PutBitContext *pb, int16_t *in,
 +        int blocks_per_slice, int *qmat)
 +{
 +    int prev_dc, code;
 +    int i, sign, idx;
 +    int new_dc, delta, diff_sign, new_code;
 +
 +    prev_dc = QSCALE(qmat, 0, in[0] - 16384);
 +    code = TO_GOLOMB(prev_dc);
 +    encode_codeword(pb, code, FIRST_DC_CB);
 +
 +    code = 5; sign = 0; idx = 64;
 +    for (i = 1; i < blocks_per_slice; i++, idx += 64) {
 +        new_dc    = QSCALE(qmat, 0, in[idx] - 16384);
 +        delta     = new_dc - prev_dc;
 +        diff_sign = DIFF_SIGN(delta, sign);
 +        new_code  = TO_GOLOMB2(get_level(delta), diff_sign);
 +
 +        encode_codeword(pb, new_code, dc_codebook[FFMIN(code, 6)]);
 +
 +        code      = new_code;
 +        sign      = delta >> 31;
 +        prev_dc   = new_dc;
 +    }
 +}
 +
 +static const uint8_t run_to_cb[16] = { 0x06, 0x06, 0x05, 0x05, 0x04, 0x29,
 +        0x29, 0x29, 0x29, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x4C };
 +static const uint8_t lev_to_cb[10] = { 0x04, 0x0A, 0x05, 0x06, 0x04, 0x28,
 +        0x28, 0x28, 0x28, 0x4C };
 +
 +static void encode_ac_coeffs(AVCodecContext *avctx, PutBitContext *pb,
 +        int16_t *in, int blocks_per_slice, int *qmat)
 +{
 +    int prev_run = 4;
 +    int prev_level = 2;
 +
 +    int run = 0, level, code, i, j;
 +    for (i = 1; i < 64; i++) {
 +        int indp = progressive_scan[i];
 +        for (j = 0; j < blocks_per_slice; j++) {
 +            int val = QSCALE(qmat, indp, in[(j << 6) + indp]);
 +            if (val) {
 +                encode_codeword(pb, run, run_to_cb[FFMIN(prev_run, 15)]);
 +
 +                prev_run   = run;
 +                run        = 0;
 +                level      = get_level(val);
 +                code       = level - 1;
 +
 +                encode_codeword(pb, code, lev_to_cb[FFMIN(prev_level, 9)]);
 +
 +                prev_level = level;
 +
 +                put_bits(pb, 1, IS_NEGATIVE(val));
 +            } else {
 +                ++run;
 +            }
 +        }
 +    }
 +}
 +
 +static void get(uint8_t *pixels, int stride, int16_t* block)
 +{
 +    int i;
 +
 +    for (i = 0; i < 8; i++) {
 +        AV_WN64(block, AV_RN64(pixels));
 +        AV_WN64(block+4, AV_RN64(pixels+8));
 +        pixels += stride;
 +        block += 8;
 +    }
 +}
 +
 +static void fdct_get(FDCTDSPContext *fdsp, uint8_t *pixels, int stride, int16_t* block)
 +{
 +    get(pixels, stride, block);
 +    fdsp->fdct(block);
 +}
 +
 +static int encode_slice_plane(AVCodecContext *avctx, int mb_count,
 +        uint8_t *src, int src_stride, uint8_t *buf, unsigned buf_size,
 +        int *qmat, int chroma)
 +{
 +    ProresContext* ctx = avctx->priv_data;
 +    FDCTDSPContext *fdsp = &ctx->fdsp;
 +    DECLARE_ALIGNED(16, int16_t, blocks)[DEFAULT_SLICE_MB_WIDTH << 8], *block;
 +    int i, blocks_per_slice;
 +    PutBitContext pb;
 +
 +    block = blocks;
 +    for (i = 0; i < mb_count; i++) {
 +        fdct_get(fdsp, src,                  src_stride, block + (0 << 6));
 +        fdct_get(fdsp, src + 8 * src_stride, src_stride, block + ((2 - chroma) << 6));
 +        if (!chroma) {
 +            fdct_get(fdsp, src + 16,                  src_stride, block + (1 << 6));
 +            fdct_get(fdsp, src + 16 + 8 * src_stride, src_stride, block + (3 << 6));
 +        }
 +
 +        block += (256 >> chroma);
 +        src   += (32  >> chroma);
 +    }
 +
 +    blocks_per_slice = mb_count << (2 - chroma);
 +    init_put_bits(&pb, buf, buf_size << 3);
 +
 +    encode_dc_coeffs(&pb, blocks, blocks_per_slice, qmat);
 +    encode_ac_coeffs(avctx, &pb, blocks, blocks_per_slice, qmat);
 +
 +    flush_put_bits(&pb);
 +    return put_bits_ptr(&pb) - pb.buf;
 +}
 +
 +static av_always_inline unsigned encode_slice_data(AVCodecContext *avctx,
 +        uint8_t *dest_y, uint8_t *dest_u, uint8_t *dest_v, int luma_stride,
 +        int chroma_stride, unsigned mb_count, uint8_t *buf, unsigned data_size,
 +        unsigned* y_data_size, unsigned* u_data_size, unsigned* v_data_size,
 +        int qp)
 +{
 +    ProresContext* ctx = avctx->priv_data;
 +
 +    *y_data_size = encode_slice_plane(avctx, mb_count, dest_y, luma_stride,
 +            buf, data_size, ctx->qmat_luma[qp - 1], 0);
 +
 +    if (!(avctx->flags & CODEC_FLAG_GRAY)) {
 +        *u_data_size = encode_slice_plane(avctx, mb_count, dest_u,
 +                chroma_stride, buf + *y_data_size, data_size - *y_data_size,
 +                ctx->qmat_chroma[qp - 1], 1);
 +
 +        *v_data_size = encode_slice_plane(avctx, mb_count, dest_v,
 +                chroma_stride, buf + *y_data_size + *u_data_size,
 +                data_size - *y_data_size - *u_data_size,
 +                ctx->qmat_chroma[qp - 1], 1);
 +    }
 +
 +    return *y_data_size + *u_data_size + *v_data_size;
 +}
 +
 +static void subimage_with_fill(uint16_t *src, unsigned x, unsigned y,
 +        unsigned stride, unsigned width, unsigned height, uint16_t *dst,
 +        unsigned dst_width, unsigned dst_height)
 +{
 +
 +    int box_width = FFMIN(width - x, dst_width);
 +    int box_height = FFMIN(height - y, dst_height);
 +    int i, j, src_stride = stride >> 1;
 +    uint16_t last_pix, *last_line;
 +
 +    src += y * src_stride + x;
 +    for (i = 0; i < box_height; ++i) {
 +        for (j = 0; j < box_width; ++j) {
 +            dst[j] = src[j];
 +        }
 +        last_pix = dst[j - 1];
 +        for (; j < dst_width; j++)
 +            dst[j] = last_pix;
 +        src += src_stride;
 +        dst += dst_width;
 +    }
 +    last_line = dst - dst_width;
 +    for (; i < dst_height; i++) {
 +        for (j = 0; j < dst_width; ++j) {
 +            dst[j] = last_line[j];
 +        }
 +        dst += dst_width;
 +    }
 +}
 +
 +static int encode_slice(AVCodecContext *avctx, const AVFrame *pic, int mb_x,
 +        int mb_y, unsigned mb_count, uint8_t *buf, unsigned data_size,
 +        int unsafe, int *qp)
 +{
 +    int luma_stride, chroma_stride;
 +    int hdr_size = 6, slice_size;
 +    uint8_t *dest_y, *dest_u, *dest_v;
 +    unsigned y_data_size = 0, u_data_size = 0, v_data_size = 0;
 +    ProresContext* ctx = avctx->priv_data;
 +    int tgt_bits   = (mb_count * bitrate_table[avctx->profile]) >> 2;
 +    int low_bytes  = (tgt_bits - (tgt_bits >> 3)) >> 3; // 12% bitrate fluctuation
 +    int high_bytes = (tgt_bits + (tgt_bits >> 3)) >> 3;
 +
 +    luma_stride   = pic->linesize[0];
 +    chroma_stride = pic->linesize[1];
 +
 +    dest_y = pic->data[0] + (mb_y << 4) * luma_stride   + (mb_x << 5);
 +    dest_u = pic->data[1] + (mb_y << 4) * chroma_stride + (mb_x << 4);
 +    dest_v = pic->data[2] + (mb_y << 4) * chroma_stride + (mb_x << 4);
 +
 +    if (unsafe) {
 +
 +        subimage_with_fill((uint16_t *) pic->data[0], mb_x << 4, mb_y << 4,
 +                luma_stride, avctx->width, avctx->height,
 +                (uint16_t *) ctx->fill_y, mb_count << 4, 16);
 +        subimage_with_fill((uint16_t *) pic->data[1], mb_x << 3, mb_y << 4,
 +                chroma_stride, avctx->width >> 1, avctx->height,
 +                (uint16_t *) ctx->fill_u, mb_count << 3, 16);
 +        subimage_with_fill((uint16_t *) pic->data[2], mb_x << 3, mb_y << 4,
 +                chroma_stride, avctx->width >> 1, avctx->height,
 +                (uint16_t *) ctx->fill_v, mb_count << 3, 16);
 +
 +        encode_slice_data(avctx, ctx->fill_y, ctx->fill_u, ctx->fill_v,
 +                mb_count << 5, mb_count << 4, mb_count, buf + hdr_size,
 +                data_size - hdr_size, &y_data_size, &u_data_size, &v_data_size,
 +                *qp);
 +    } else {
 +        slice_size = encode_slice_data(avctx, dest_y, dest_u, dest_v,
 +                luma_stride, chroma_stride, mb_count, buf + hdr_size,
 +                data_size - hdr_size, &y_data_size, &u_data_size, &v_data_size,
 +                *qp);
 +
 +        if (slice_size > high_bytes && *qp < qp_end_table[avctx->profile]) {
 +            do {
 +                *qp += 1;
 +                slice_size = encode_slice_data(avctx, dest_y, dest_u, dest_v,
 +                        luma_stride, chroma_stride, mb_count, buf + hdr_size,
 +                        data_size - hdr_size, &y_data_size, &u_data_size,
 +                        &v_data_size, *qp);
 +            } while (slice_size > high_bytes && *qp < qp_end_table[avctx->profile]);
 +        } else if (slice_size < low_bytes && *qp
 +                > qp_start_table[avctx->profile]) {
 +            do {
 +                *qp -= 1;
 +                slice_size = encode_slice_data(avctx, dest_y, dest_u, dest_v,
 +                        luma_stride, chroma_stride, mb_count, buf + hdr_size,
 +                        data_size - hdr_size, &y_data_size, &u_data_size,
 +                        &v_data_size, *qp);
 +            } while (slice_size < low_bytes && *qp > qp_start_table[avctx->profile]);
 +        }
 +    }
 +
 +    buf[0] = hdr_size << 3;
 +    buf[1] = *qp;
 +    AV_WB16(buf + 2, y_data_size);
 +    AV_WB16(buf + 4, u_data_size);
 +
 +    return hdr_size + y_data_size + u_data_size + v_data_size;
 +}
 +
 +static int prores_encode_picture(AVCodecContext *avctx, const AVFrame *pic,
 +        uint8_t *buf, const int buf_size)
 +{
 +    int mb_width = (avctx->width + 15) >> 4;
 +    int mb_height = (avctx->height + 15) >> 4;
 +    int hdr_size, sl_size, i;
 +    int mb_y, sl_data_size, qp;
 +    int unsafe_bot, unsafe_right;
 +    uint8_t *sl_data, *sl_data_sizes;
 +    int slice_per_line = 0, rem = mb_width;
 +
 +    for (i = av_log2(DEFAULT_SLICE_MB_WIDTH); i >= 0; --i) {
 +        slice_per_line += rem >> i;
 +        rem &= (1 << i) - 1;
 +    }
 +
 +    qp = qp_start_table[avctx->profile];
 +    hdr_size = 8; sl_data_size = buf_size - hdr_size;
 +    sl_data_sizes = buf + hdr_size;
 +    sl_data = sl_data_sizes + (slice_per_line * mb_height * 2);
 +    for (mb_y = 0; mb_y < mb_height; mb_y++) {
 +        int mb_x = 0;
 +        int slice_mb_count = DEFAULT_SLICE_MB_WIDTH;
 +        while (mb_x < mb_width) {
 +            while (mb_width - mb_x < slice_mb_count)
 +                slice_mb_count >>= 1;
 +
 +            unsafe_bot = (avctx->height & 0xf) && (mb_y == mb_height - 1);
 +            unsafe_right = (avctx->width & 0xf) && (mb_x + slice_mb_count == mb_width);
 +
 +            sl_size = encode_slice(avctx, pic, mb_x, mb_y, slice_mb_count,
 +                    sl_data, sl_data_size, unsafe_bot || unsafe_right, &qp);
 +
 +            bytestream_put_be16(&sl_data_sizes, sl_size);
 +            sl_data           += sl_size;
 +            sl_data_size      -= sl_size;
 +            mb_x              += slice_mb_count;
 +        }
 +    }
 +
 +    buf[0] = hdr_size << 3;
 +    AV_WB32(buf + 1, sl_data - buf);
 +    AV_WB16(buf + 5, slice_per_line * mb_height);
 +    buf[7] = av_log2(DEFAULT_SLICE_MB_WIDTH) << 4;
 +
 +    return sl_data - buf;
 +}
 +
 +static int prores_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
 +                               const AVFrame *pict, int *got_packet)
 +{
 +    int header_size = 148;
 +    uint8_t *buf;
 +    int pic_size, ret;
 +    int frame_size = FFALIGN(avctx->width, 16) * FFALIGN(avctx->height, 16)*16 + 500 + FF_MIN_BUFFER_SIZE; //FIXME choose tighter limit
 +
 +
 +    if ((ret = ff_alloc_packet2(avctx, pkt, frame_size + FF_MIN_BUFFER_SIZE)) < 0)
 +        return ret;
 +
 +    buf = pkt->data;
 +    pic_size = prores_encode_picture(avctx, pict, buf + header_size + 8,
 +            pkt->size - header_size - 8);
 +
 +    bytestream_put_be32(&buf, pic_size + 8 + header_size);
 +    bytestream_put_buffer(&buf, "icpf", 4);
 +
 +    bytestream_put_be16(&buf, header_size);
 +    bytestream_put_be16(&buf, 0);
 +    bytestream_put_buffer(&buf, "fmpg", 4);
 +    bytestream_put_be16(&buf, avctx->width);
 +    bytestream_put_be16(&buf, avctx->height);
 +    *buf++ = 0x83; // {10}(422){00}{00}(frame){11}
 +    *buf++ = 0;
 +    *buf++ = 2;
 +    *buf++ = 2;
 +    *buf++ = 6;
 +    *buf++ = 32;
 +    *buf++ = 0;
 +    *buf++ = 3;
 +
 +    bytestream_put_buffer(&buf, QMAT_LUMA[avctx->profile],   64);
 +    bytestream_put_buffer(&buf, QMAT_CHROMA[avctx->profile], 64);
 +
 +    pkt->flags |= AV_PKT_FLAG_KEY;
 +    pkt->size = pic_size + 8 + header_size;
 +    *got_packet = 1;
 +
 +    return 0;
 +}
 +
 +static void scale_mat(const uint8_t* src, int* dst, int scale)
 +{
 +    int i;
 +    for (i = 0; i < 64; i++)
 +        dst[i] = src[i] * scale;
 +}
 +
 +static av_cold int prores_encode_init(AVCodecContext *avctx)
 +{
 +    int i;
 +    ProresContext* ctx = avctx->priv_data;
 +
 +    if (avctx->pix_fmt != AV_PIX_FMT_YUV422P10) {
 +        av_log(avctx, AV_LOG_ERROR, "need YUV422P10\n");
 +        return -1;
 +    }
 +    avctx->bits_per_raw_sample = 10;
 +
 +    if (avctx->width & 0x1) {
 +        av_log(avctx, AV_LOG_ERROR,
 +                "frame width needs to be multiple of 2\n");
 +        return -1;
 +    }
 +
 +    if (avctx->width > 65534 || avctx->height > 65535) {
 +        av_log(avctx, AV_LOG_ERROR,
 +                "The maximum dimensions are 65534x65535\n");
 +        return AVERROR(EINVAL);
 +    }
 +
 +    if ((avctx->height & 0xf) || (avctx->width & 0xf)) {
 +        ctx->fill_y = av_malloc(4 * (DEFAULT_SLICE_MB_WIDTH << 8));
 +        if (!ctx->fill_y)
 +            return AVERROR(ENOMEM);
 +        ctx->fill_u = ctx->fill_y + (DEFAULT_SLICE_MB_WIDTH << 9);
 +        ctx->fill_v = ctx->fill_u + (DEFAULT_SLICE_MB_WIDTH << 8);
 +    }
 +
 +    if (avctx->profile == FF_PROFILE_UNKNOWN) {
 +        avctx->profile = FF_PROFILE_PRORES_STANDARD;
 +        av_log(avctx, AV_LOG_INFO,
 +                "encoding with ProRes standard (apcn) profile\n");
 +
 +    } else if (avctx->profile < FF_PROFILE_PRORES_PROXY
 +            || avctx->profile > FF_PROFILE_PRORES_HQ) {
 +        av_log(
 +                avctx,
 +                AV_LOG_ERROR,
 +                "unknown profile %d, use [0 - apco, 1 - apcs, 2 - apcn (default), 3 - apch]\n",
 +                avctx->profile);
 +        return -1;
 +    }
 +
 +    ff_fdctdsp_init(&ctx->fdsp, avctx);
 +
 +    avctx->codec_tag = AV_RL32((const uint8_t*)profiles[avctx->profile].name);
 +
 +    for (i = 1; i <= 16; i++) {
 +        scale_mat(QMAT_LUMA[avctx->profile]  , ctx->qmat_luma[i - 1]  , i);
 +        scale_mat(QMAT_CHROMA[avctx->profile], ctx->qmat_chroma[i - 1], i);
 +    }
 +
 +    avctx->coded_frame = av_frame_alloc();
 +    avctx->coded_frame->key_frame = 1;
 +    avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I;
 +
 +    return 0;
 +}
 +
 +static av_cold int prores_encode_close(AVCodecContext *avctx)
 +{
 +    ProresContext* ctx = avctx->priv_data;
 +    av_freep(&avctx->coded_frame);
 +    av_freep(&ctx->fill_y);
 +
 +    return 0;
 +}
 +
 +AVCodec ff_prores_aw_encoder = {
 +    .name           = "prores_aw",
 +    .long_name      = NULL_IF_CONFIG_SMALL("Apple ProRes"),
 +    .type           = AVMEDIA_TYPE_VIDEO,
 +    .id             = AV_CODEC_ID_PRORES,
 +    .priv_data_size = sizeof(ProresContext),
 +    .init           = prores_encode_init,
 +    .close          = prores_encode_close,
 +    .encode2        = prores_encode_frame,
 +    .pix_fmts       = (const enum AVPixelFormat[]){AV_PIX_FMT_YUV422P10, AV_PIX_FMT_NONE},
 +    .capabilities   = CODEC_CAP_FRAME_THREADS | CODEC_CAP_INTRA_ONLY,
 +    .profiles       = profiles
 +};
 +
 +AVCodec ff_prores_encoder = {
 +    .name           = "prores",
 +    .long_name      = NULL_IF_CONFIG_SMALL("Apple ProRes"),
 +    .type           = AVMEDIA_TYPE_VIDEO,
 +    .id             = AV_CODEC_ID_PRORES,
 +    .priv_data_size = sizeof(ProresContext),
 +    .init           = prores_encode_init,
 +    .close          = prores_encode_close,
 +    .encode2        = prores_encode_frame,
 +    .pix_fmts       = (const enum AVPixelFormat[]){AV_PIX_FMT_YUV422P10, AV_PIX_FMT_NONE},
 +    .capabilities   = CODEC_CAP_FRAME_THREADS | CODEC_CAP_INTRA_ONLY,
 +    .profiles       = profiles
 +};
index 668fe72,0000000..dc80ce6
mode 100644,000000..100644
--- /dev/null
@@@ -1,723 -1,0 +1,723 @@@
- #include "dsputil.h"
 +/*
 + * Copyright (C) 2004 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
 + */
 +
 +#include "libavutil/intmath.h"
 +#include "libavutil/log.h"
 +#include "libavutil/opt.h"
 +#include "avcodec.h"
-     ff_dsputil_init(&s->dsp, avctx);
++#include "me_cmp.h"
 +#include "snow_dwt.h"
 +#include "internal.h"
 +#include "snow.h"
 +#include "snowdata.h"
 +
 +#include "rangecoder.h"
 +#include "mathops.h"
 +#include "h263.h"
 +
 +
 +void ff_snow_inner_add_yblock(const uint8_t *obmc, const int obmc_stride, uint8_t * * block, int b_w, int b_h,
 +                              int src_x, int src_y, int src_stride, slice_buffer * sb, int add, uint8_t * dst8){
 +    int y, x;
 +    IDWTELEM * dst;
 +    for(y=0; y<b_h; y++){
 +        //FIXME ugly misuse of obmc_stride
 +        const uint8_t *obmc1= obmc + y*obmc_stride;
 +        const uint8_t *obmc2= obmc1+ (obmc_stride>>1);
 +        const uint8_t *obmc3= obmc1+ obmc_stride*(obmc_stride>>1);
 +        const uint8_t *obmc4= obmc3+ (obmc_stride>>1);
 +        dst = slice_buffer_get_line(sb, src_y + y);
 +        for(x=0; x<b_w; x++){
 +            int v=   obmc1[x] * block[3][x + y*src_stride]
 +                    +obmc2[x] * block[2][x + y*src_stride]
 +                    +obmc3[x] * block[1][x + y*src_stride]
 +                    +obmc4[x] * block[0][x + y*src_stride];
 +
 +            v <<= 8 - LOG2_OBMC_MAX;
 +            if(FRAC_BITS != 8){
 +                v >>= 8 - FRAC_BITS;
 +            }
 +            if(add){
 +                v += dst[x + src_x];
 +                v = (v + (1<<(FRAC_BITS-1))) >> FRAC_BITS;
 +                if(v&(~255)) v= ~(v>>31);
 +                dst8[x + y*src_stride] = v;
 +            }else{
 +                dst[x + src_x] -= v;
 +            }
 +        }
 +    }
 +}
 +
 +int ff_snow_get_buffer(SnowContext *s, AVFrame *frame)
 +{
 +    int ret, i;
 +    int edges_needed = av_codec_is_encoder(s->avctx->codec);
 +
 +    frame->width  = s->avctx->width ;
 +    frame->height = s->avctx->height;
 +    if (edges_needed) {
 +        frame->width  += 2 * EDGE_WIDTH;
 +        frame->height += 2 * EDGE_WIDTH;
 +    }
 +    if ((ret = ff_get_buffer(s->avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0)
 +        return ret;
 +    if (edges_needed) {
 +        for (i = 0; frame->data[i]; i++) {
 +            int offset = (EDGE_WIDTH >> (i ? s->chroma_v_shift : 0)) *
 +                            frame->linesize[i] +
 +                            (EDGE_WIDTH >> (i ? s->chroma_h_shift : 0));
 +            frame->data[i] += offset;
 +        }
 +        frame->width  = s->avctx->width;
 +        frame->height = s->avctx->height;
 +    }
 +
 +    return 0;
 +}
 +
 +void ff_snow_reset_contexts(SnowContext *s){ //FIXME better initial contexts
 +    int plane_index, level, orientation;
 +
 +    for(plane_index=0; plane_index<3; plane_index++){
 +        for(level=0; level<MAX_DECOMPOSITIONS; level++){
 +            for(orientation=level ? 1:0; orientation<4; orientation++){
 +                memset(s->plane[plane_index].band[level][orientation].state, MID_STATE, sizeof(s->plane[plane_index].band[level][orientation].state));
 +            }
 +        }
 +    }
 +    memset(s->header_state, MID_STATE, sizeof(s->header_state));
 +    memset(s->block_state, MID_STATE, sizeof(s->block_state));
 +}
 +
 +int ff_snow_alloc_blocks(SnowContext *s){
 +    int w= FF_CEIL_RSHIFT(s->avctx->width,  LOG2_MB_SIZE);
 +    int h= FF_CEIL_RSHIFT(s->avctx->height, LOG2_MB_SIZE);
 +
 +    s->b_width = w;
 +    s->b_height= h;
 +
 +    av_free(s->block);
 +    s->block= av_mallocz_array(w * h,  sizeof(BlockNode) << (s->block_max_depth*2));
 +    if (!s->block)
 +        return AVERROR(ENOMEM);
 +
 +    return 0;
 +}
 +
 +static av_cold void init_qexp(void){
 +    int i;
 +    double v=128;
 +
 +    for(i=0; i<QROOT; i++){
 +        ff_qexp[i]= lrintf(v);
 +        v *= pow(2, 1.0 / QROOT);
 +    }
 +}
 +static void mc_block(Plane *p, uint8_t *dst, const uint8_t *src, int stride, int b_w, int b_h, int dx, int dy){
 +    static const uint8_t weight[64]={
 +    8,7,6,5,4,3,2,1,
 +    7,7,0,0,0,0,0,1,
 +    6,0,6,0,0,0,2,0,
 +    5,0,0,5,0,3,0,0,
 +    4,0,0,0,4,0,0,0,
 +    3,0,0,5,0,3,0,0,
 +    2,0,6,0,0,0,2,0,
 +    1,7,0,0,0,0,0,1,
 +    };
 +
 +    static const uint8_t brane[256]={
 +    0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x11,0x12,0x12,0x12,0x12,0x12,0x12,0x12,
 +    0x04,0x05,0xcc,0xcc,0xcc,0xcc,0xcc,0x41,0x15,0x16,0xcc,0xcc,0xcc,0xcc,0xcc,0x52,
 +    0x04,0xcc,0x05,0xcc,0xcc,0xcc,0x41,0xcc,0x15,0xcc,0x16,0xcc,0xcc,0xcc,0x52,0xcc,
 +    0x04,0xcc,0xcc,0x05,0xcc,0x41,0xcc,0xcc,0x15,0xcc,0xcc,0x16,0xcc,0x52,0xcc,0xcc,
 +    0x04,0xcc,0xcc,0xcc,0x41,0xcc,0xcc,0xcc,0x15,0xcc,0xcc,0xcc,0x16,0xcc,0xcc,0xcc,
 +    0x04,0xcc,0xcc,0x41,0xcc,0x05,0xcc,0xcc,0x15,0xcc,0xcc,0x52,0xcc,0x16,0xcc,0xcc,
 +    0x04,0xcc,0x41,0xcc,0xcc,0xcc,0x05,0xcc,0x15,0xcc,0x52,0xcc,0xcc,0xcc,0x16,0xcc,
 +    0x04,0x41,0xcc,0xcc,0xcc,0xcc,0xcc,0x05,0x15,0x52,0xcc,0xcc,0xcc,0xcc,0xcc,0x16,
 +    0x44,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x55,0x56,0x56,0x56,0x56,0x56,0x56,0x56,
 +    0x48,0x49,0xcc,0xcc,0xcc,0xcc,0xcc,0x85,0x59,0x5A,0xcc,0xcc,0xcc,0xcc,0xcc,0x96,
 +    0x48,0xcc,0x49,0xcc,0xcc,0xcc,0x85,0xcc,0x59,0xcc,0x5A,0xcc,0xcc,0xcc,0x96,0xcc,
 +    0x48,0xcc,0xcc,0x49,0xcc,0x85,0xcc,0xcc,0x59,0xcc,0xcc,0x5A,0xcc,0x96,0xcc,0xcc,
 +    0x48,0xcc,0xcc,0xcc,0x49,0xcc,0xcc,0xcc,0x59,0xcc,0xcc,0xcc,0x96,0xcc,0xcc,0xcc,
 +    0x48,0xcc,0xcc,0x85,0xcc,0x49,0xcc,0xcc,0x59,0xcc,0xcc,0x96,0xcc,0x5A,0xcc,0xcc,
 +    0x48,0xcc,0x85,0xcc,0xcc,0xcc,0x49,0xcc,0x59,0xcc,0x96,0xcc,0xcc,0xcc,0x5A,0xcc,
 +    0x48,0x85,0xcc,0xcc,0xcc,0xcc,0xcc,0x49,0x59,0x96,0xcc,0xcc,0xcc,0xcc,0xcc,0x5A,
 +    };
 +
 +    static const uint8_t needs[16]={
 +    0,1,0,0,
 +    2,4,2,0,
 +    0,1,0,0,
 +    15
 +    };
 +
 +    int x, y, b, r, l;
 +    int16_t tmpIt   [64*(32+HTAPS_MAX)];
 +    uint8_t tmp2t[3][64*(32+HTAPS_MAX)];
 +    int16_t *tmpI= tmpIt;
 +    uint8_t *tmp2= tmp2t[0];
 +    const uint8_t *hpel[11];
 +    av_assert2(dx<16 && dy<16);
 +    r= brane[dx + 16*dy]&15;
 +    l= brane[dx + 16*dy]>>4;
 +
 +    b= needs[l] | needs[r];
 +    if(p && !p->diag_mc)
 +        b= 15;
 +
 +    if(b&5){
 +        for(y=0; y < b_h+HTAPS_MAX-1; y++){
 +            for(x=0; x < b_w; x++){
 +                int a_1=src[x + HTAPS_MAX/2-4];
 +                int a0= src[x + HTAPS_MAX/2-3];
 +                int a1= src[x + HTAPS_MAX/2-2];
 +                int a2= src[x + HTAPS_MAX/2-1];
 +                int a3= src[x + HTAPS_MAX/2+0];
 +                int a4= src[x + HTAPS_MAX/2+1];
 +                int a5= src[x + HTAPS_MAX/2+2];
 +                int a6= src[x + HTAPS_MAX/2+3];
 +                int am=0;
 +                if(!p || p->fast_mc){
 +                    am= 20*(a2+a3) - 5*(a1+a4) + (a0+a5);
 +                    tmpI[x]= am;
 +                    am= (am+16)>>5;
 +                }else{
 +                    am= p->hcoeff[0]*(a2+a3) + p->hcoeff[1]*(a1+a4) + p->hcoeff[2]*(a0+a5) + p->hcoeff[3]*(a_1+a6);
 +                    tmpI[x]= am;
 +                    am= (am+32)>>6;
 +                }
 +
 +                if(am&(~255)) am= ~(am>>31);
 +                tmp2[x]= am;
 +            }
 +            tmpI+= 64;
 +            tmp2+= 64;
 +            src += stride;
 +        }
 +        src -= stride*y;
 +    }
 +    src += HTAPS_MAX/2 - 1;
 +    tmp2= tmp2t[1];
 +
 +    if(b&2){
 +        for(y=0; y < b_h; y++){
 +            for(x=0; x < b_w+1; x++){
 +                int a_1=src[x + (HTAPS_MAX/2-4)*stride];
 +                int a0= src[x + (HTAPS_MAX/2-3)*stride];
 +                int a1= src[x + (HTAPS_MAX/2-2)*stride];
 +                int a2= src[x + (HTAPS_MAX/2-1)*stride];
 +                int a3= src[x + (HTAPS_MAX/2+0)*stride];
 +                int a4= src[x + (HTAPS_MAX/2+1)*stride];
 +                int a5= src[x + (HTAPS_MAX/2+2)*stride];
 +                int a6= src[x + (HTAPS_MAX/2+3)*stride];
 +                int am=0;
 +                if(!p || p->fast_mc)
 +                    am= (20*(a2+a3) - 5*(a1+a4) + (a0+a5) + 16)>>5;
 +                else
 +                    am= (p->hcoeff[0]*(a2+a3) + p->hcoeff[1]*(a1+a4) + p->hcoeff[2]*(a0+a5) + p->hcoeff[3]*(a_1+a6) + 32)>>6;
 +
 +                if(am&(~255)) am= ~(am>>31);
 +                tmp2[x]= am;
 +            }
 +            src += stride;
 +            tmp2+= 64;
 +        }
 +        src -= stride*y;
 +    }
 +    src += stride*(HTAPS_MAX/2 - 1);
 +    tmp2= tmp2t[2];
 +    tmpI= tmpIt;
 +    if(b&4){
 +        for(y=0; y < b_h; y++){
 +            for(x=0; x < b_w; x++){
 +                int a_1=tmpI[x + (HTAPS_MAX/2-4)*64];
 +                int a0= tmpI[x + (HTAPS_MAX/2-3)*64];
 +                int a1= tmpI[x + (HTAPS_MAX/2-2)*64];
 +                int a2= tmpI[x + (HTAPS_MAX/2-1)*64];
 +                int a3= tmpI[x + (HTAPS_MAX/2+0)*64];
 +                int a4= tmpI[x + (HTAPS_MAX/2+1)*64];
 +                int a5= tmpI[x + (HTAPS_MAX/2+2)*64];
 +                int a6= tmpI[x + (HTAPS_MAX/2+3)*64];
 +                int am=0;
 +                if(!p || p->fast_mc)
 +                    am= (20*(a2+a3) - 5*(a1+a4) + (a0+a5) + 512)>>10;
 +                else
 +                    am= (p->hcoeff[0]*(a2+a3) + p->hcoeff[1]*(a1+a4) + p->hcoeff[2]*(a0+a5) + p->hcoeff[3]*(a_1+a6) + 2048)>>12;
 +                if(am&(~255)) am= ~(am>>31);
 +                tmp2[x]= am;
 +            }
 +            tmpI+= 64;
 +            tmp2+= 64;
 +        }
 +    }
 +
 +    hpel[ 0]= src;
 +    hpel[ 1]= tmp2t[0] + 64*(HTAPS_MAX/2-1);
 +    hpel[ 2]= src + 1;
 +
 +    hpel[ 4]= tmp2t[1];
 +    hpel[ 5]= tmp2t[2];
 +    hpel[ 6]= tmp2t[1] + 1;
 +
 +    hpel[ 8]= src + stride;
 +    hpel[ 9]= hpel[1] + 64;
 +    hpel[10]= hpel[8] + 1;
 +
 +#define MC_STRIDE(x) (needs[x] ? 64 : stride)
 +
 +    if(b==15){
 +        int dxy = dx / 8 + dy / 8 * 4;
 +        const uint8_t *src1 = hpel[dxy    ];
 +        const uint8_t *src2 = hpel[dxy + 1];
 +        const uint8_t *src3 = hpel[dxy + 4];
 +        const uint8_t *src4 = hpel[dxy + 5];
 +        int stride1 = MC_STRIDE(dxy);
 +        int stride2 = MC_STRIDE(dxy + 1);
 +        int stride3 = MC_STRIDE(dxy + 4);
 +        int stride4 = MC_STRIDE(dxy + 5);
 +        dx&=7;
 +        dy&=7;
 +        for(y=0; y < b_h; y++){
 +            for(x=0; x < b_w; x++){
 +                dst[x]= ((8-dx)*(8-dy)*src1[x] + dx*(8-dy)*src2[x]+
 +                         (8-dx)*   dy *src3[x] + dx*   dy *src4[x]+32)>>6;
 +            }
 +            src1+=stride1;
 +            src2+=stride2;
 +            src3+=stride3;
 +            src4+=stride4;
 +            dst +=stride;
 +        }
 +    }else{
 +        const uint8_t *src1= hpel[l];
 +        const uint8_t *src2= hpel[r];
 +        int stride1 = MC_STRIDE(l);
 +        int stride2 = MC_STRIDE(r);
 +        int a= weight[((dx&7) + (8*(dy&7)))];
 +        int b= 8-a;
 +        for(y=0; y < b_h; y++){
 +            for(x=0; x < b_w; x++){
 +                dst[x]= (a*src1[x] + b*src2[x] + 4)>>3;
 +            }
 +            src1+=stride1;
 +            src2+=stride2;
 +            dst +=stride;
 +        }
 +    }
 +}
 +
 +void ff_snow_pred_block(SnowContext *s, uint8_t *dst, uint8_t *tmp, ptrdiff_t stride, int sx, int sy, int b_w, int b_h, BlockNode *block, int plane_index, int w, int h){
 +    if(block->type & BLOCK_INTRA){
 +        int x, y;
 +        const unsigned color  = block->color[plane_index];
 +        const unsigned color4 = color*0x01010101;
 +        if(b_w==32){
 +            for(y=0; y < b_h; y++){
 +                *(uint32_t*)&dst[0 + y*stride]= color4;
 +                *(uint32_t*)&dst[4 + y*stride]= color4;
 +                *(uint32_t*)&dst[8 + y*stride]= color4;
 +                *(uint32_t*)&dst[12+ y*stride]= color4;
 +                *(uint32_t*)&dst[16+ y*stride]= color4;
 +                *(uint32_t*)&dst[20+ y*stride]= color4;
 +                *(uint32_t*)&dst[24+ y*stride]= color4;
 +                *(uint32_t*)&dst[28+ y*stride]= color4;
 +            }
 +        }else if(b_w==16){
 +            for(y=0; y < b_h; y++){
 +                *(uint32_t*)&dst[0 + y*stride]= color4;
 +                *(uint32_t*)&dst[4 + y*stride]= color4;
 +                *(uint32_t*)&dst[8 + y*stride]= color4;
 +                *(uint32_t*)&dst[12+ y*stride]= color4;
 +            }
 +        }else if(b_w==8){
 +            for(y=0; y < b_h; y++){
 +                *(uint32_t*)&dst[0 + y*stride]= color4;
 +                *(uint32_t*)&dst[4 + y*stride]= color4;
 +            }
 +        }else if(b_w==4){
 +            for(y=0; y < b_h; y++){
 +                *(uint32_t*)&dst[0 + y*stride]= color4;
 +            }
 +        }else{
 +            for(y=0; y < b_h; y++){
 +                for(x=0; x < b_w; x++){
 +                    dst[x + y*stride]= color;
 +                }
 +            }
 +        }
 +    }else{
 +        uint8_t *src= s->last_picture[block->ref]->data[plane_index];
 +        const int scale= plane_index ?  (2*s->mv_scale)>>s->chroma_h_shift : 2*s->mv_scale;
 +        int mx= block->mx*scale;
 +        int my= block->my*scale;
 +        const int dx= mx&15;
 +        const int dy= my&15;
 +        const int tab_index= 3 - (b_w>>2) + (b_w>>4);
 +        sx += (mx>>4) - (HTAPS_MAX/2-1);
 +        sy += (my>>4) - (HTAPS_MAX/2-1);
 +        src += sx + sy*stride;
 +        if(   (unsigned)sx >= FFMAX(w - b_w - (HTAPS_MAX-2), 0)
 +           || (unsigned)sy >= FFMAX(h - b_h - (HTAPS_MAX-2), 0)){
 +            s->vdsp.emulated_edge_mc(tmp + MB_SIZE, src,
 +                                     stride, stride,
 +                                     b_w+HTAPS_MAX-1, b_h+HTAPS_MAX-1,
 +                                     sx, sy, w, h);
 +            src= tmp + MB_SIZE;
 +        }
 +
 +        av_assert2(s->chroma_h_shift == s->chroma_v_shift); // only one mv_scale
 +
 +        av_assert2((tab_index>=0 && tab_index<4) || b_w==32);
 +        if(    (dx&3) || (dy&3)
 +            || !(b_w == b_h || 2*b_w == b_h || b_w == 2*b_h)
 +            || (b_w&(b_w-1))
 +            || b_w == 1
 +            || b_h == 1
 +            || !s->plane[plane_index].fast_mc )
 +            mc_block(&s->plane[plane_index], dst, src, stride, b_w, b_h, dx, dy);
 +        else if(b_w==32){
 +            int y;
 +            for(y=0; y<b_h; y+=16){
 +                s->h264qpel.put_h264_qpel_pixels_tab[0][dy+(dx>>2)](dst + y*stride, src + 3 + (y+3)*stride,stride);
 +                s->h264qpel.put_h264_qpel_pixels_tab[0][dy+(dx>>2)](dst + 16 + y*stride, src + 19 + (y+3)*stride,stride);
 +            }
 +        }else if(b_w==b_h)
 +            s->h264qpel.put_h264_qpel_pixels_tab[tab_index  ][dy+(dx>>2)](dst,src + 3 + 3*stride,stride);
 +        else if(b_w==2*b_h){
 +            s->h264qpel.put_h264_qpel_pixels_tab[tab_index+1][dy+(dx>>2)](dst    ,src + 3       + 3*stride,stride);
 +            s->h264qpel.put_h264_qpel_pixels_tab[tab_index+1][dy+(dx>>2)](dst+b_h,src + 3 + b_h + 3*stride,stride);
 +        }else{
 +            av_assert2(2*b_w==b_h);
 +            s->h264qpel.put_h264_qpel_pixels_tab[tab_index  ][dy+(dx>>2)](dst           ,src + 3 + 3*stride           ,stride);
 +            s->h264qpel.put_h264_qpel_pixels_tab[tab_index  ][dy+(dx>>2)](dst+b_w*stride,src + 3 + 3*stride+b_w*stride,stride);
 +        }
 +    }
 +}
 +
 +#define mca(dx,dy,b_w)\
 +static void mc_block_hpel ## dx ## dy ## b_w(uint8_t *dst, const uint8_t *src, ptrdiff_t stride, int h){\
 +    av_assert2(h==b_w);\
 +    mc_block(NULL, dst, src-(HTAPS_MAX/2-1)-(HTAPS_MAX/2-1)*stride, stride, b_w, b_w, dx, dy);\
 +}
 +
 +mca( 0, 0,16)
 +mca( 8, 0,16)
 +mca( 0, 8,16)
 +mca( 8, 8,16)
 +mca( 0, 0,8)
 +mca( 8, 0,8)
 +mca( 0, 8,8)
 +mca( 8, 8,8)
 +
 +av_cold int ff_snow_common_init(AVCodecContext *avctx){
 +    SnowContext *s = avctx->priv_data;
 +    int width, height;
 +    int i, j;
 +
 +    s->avctx= avctx;
 +    s->max_ref_frames=1; //just make sure it's not an invalid value in case of no initial keyframe
 +
++    ff_me_cmp_init(&s->mecc, avctx);
 +    ff_hpeldsp_init(&s->hdsp, avctx->flags);
 +    ff_videodsp_init(&s->vdsp, 8);
 +    ff_dwt_init(&s->dwt);
 +    ff_h264qpel_init(&s->h264qpel, 8);
 +
 +#define mcf(dx,dy)\
 +    s->qdsp.put_qpel_pixels_tab       [0][dy+dx/4]=\
 +    s->qdsp.put_no_rnd_qpel_pixels_tab[0][dy+dx/4]=\
 +        s->h264qpel.put_h264_qpel_pixels_tab[0][dy+dx/4];\
 +    s->qdsp.put_qpel_pixels_tab       [1][dy+dx/4]=\
 +    s->qdsp.put_no_rnd_qpel_pixels_tab[1][dy+dx/4]=\
 +        s->h264qpel.put_h264_qpel_pixels_tab[1][dy+dx/4];
 +
 +    mcf( 0, 0)
 +    mcf( 4, 0)
 +    mcf( 8, 0)
 +    mcf(12, 0)
 +    mcf( 0, 4)
 +    mcf( 4, 4)
 +    mcf( 8, 4)
 +    mcf(12, 4)
 +    mcf( 0, 8)
 +    mcf( 4, 8)
 +    mcf( 8, 8)
 +    mcf(12, 8)
 +    mcf( 0,12)
 +    mcf( 4,12)
 +    mcf( 8,12)
 +    mcf(12,12)
 +
 +#define mcfh(dx,dy)\
 +    s->hdsp.put_pixels_tab       [0][dy/4+dx/8]=\
 +    s->hdsp.put_no_rnd_pixels_tab[0][dy/4+dx/8]=\
 +        mc_block_hpel ## dx ## dy ## 16;\
 +    s->hdsp.put_pixels_tab       [1][dy/4+dx/8]=\
 +    s->hdsp.put_no_rnd_pixels_tab[1][dy/4+dx/8]=\
 +        mc_block_hpel ## dx ## dy ## 8;
 +
 +    mcfh(0, 0)
 +    mcfh(8, 0)
 +    mcfh(0, 8)
 +    mcfh(8, 8)
 +
 +    init_qexp();
 +
 +//    dec += FFMAX(s->chroma_h_shift, s->chroma_v_shift);
 +
 +    width= s->avctx->width;
 +    height= s->avctx->height;
 +
 +    FF_ALLOCZ_ARRAY_OR_GOTO(avctx, s->spatial_idwt_buffer, width, height * sizeof(IDWTELEM), fail);
 +    FF_ALLOCZ_ARRAY_OR_GOTO(avctx, s->spatial_dwt_buffer,  width, height * sizeof(DWTELEM),  fail); //FIXME this does not belong here
 +    FF_ALLOCZ_ARRAY_OR_GOTO(avctx, s->temp_dwt_buffer,     width, sizeof(DWTELEM),  fail);
 +    FF_ALLOCZ_ARRAY_OR_GOTO(avctx, s->temp_idwt_buffer,    width, sizeof(IDWTELEM), fail);
 +    FF_ALLOC_ARRAY_OR_GOTO(avctx,  s->run_buffer,          ((width + 1) >> 1), ((height + 1) >> 1) * sizeof(*s->run_buffer), fail);
 +
 +    for(i=0; i<MAX_REF_FRAMES; i++) {
 +        for(j=0; j<MAX_REF_FRAMES; j++)
 +            ff_scale_mv_ref[i][j] = 256*(i+1)/(j+1);
 +        s->last_picture[i] = av_frame_alloc();
 +        if (!s->last_picture[i])
 +            goto fail;
 +    }
 +
 +    s->mconly_picture = av_frame_alloc();
 +    s->current_picture = av_frame_alloc();
 +    if (!s->mconly_picture || !s->current_picture)
 +        goto fail;
 +
 +    return 0;
 +fail:
 +    return AVERROR(ENOMEM);
 +}
 +
 +int ff_snow_common_init_after_header(AVCodecContext *avctx) {
 +    SnowContext *s = avctx->priv_data;
 +    int plane_index, level, orientation;
 +    int ret, emu_buf_size;
 +
 +    if(!s->scratchbuf) {
 +        if ((ret = ff_get_buffer(s->avctx, s->mconly_picture,
 +                                 AV_GET_BUFFER_FLAG_REF)) < 0)
 +            return ret;
 +        FF_ALLOCZ_ARRAY_OR_GOTO(avctx, s->scratchbuf, FFMAX(s->mconly_picture->linesize[0], 2*avctx->width+256), 7*MB_SIZE, fail);
 +        emu_buf_size = FFMAX(s->mconly_picture->linesize[0], 2*avctx->width+256) * (2 * MB_SIZE + HTAPS_MAX - 1);
 +        FF_ALLOC_OR_GOTO(avctx, s->emu_edge_buffer, emu_buf_size, fail);
 +    }
 +
 +    if(s->mconly_picture->format != avctx->pix_fmt) {
 +        av_log(avctx, AV_LOG_ERROR, "pixel format changed\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    for(plane_index=0; plane_index < s->nb_planes; plane_index++){
 +        int w= s->avctx->width;
 +        int h= s->avctx->height;
 +
 +        if(plane_index){
 +            w>>= s->chroma_h_shift;
 +            h>>= s->chroma_v_shift;
 +        }
 +        s->plane[plane_index].width = w;
 +        s->plane[plane_index].height= h;
 +
 +        for(level=s->spatial_decomposition_count-1; level>=0; level--){
 +            for(orientation=level ? 1 : 0; orientation<4; orientation++){
 +                SubBand *b= &s->plane[plane_index].band[level][orientation];
 +
 +                b->buf= s->spatial_dwt_buffer;
 +                b->level= level;
 +                b->stride= s->plane[plane_index].width << (s->spatial_decomposition_count - level);
 +                b->width = (w + !(orientation&1))>>1;
 +                b->height= (h + !(orientation>1))>>1;
 +
 +                b->stride_line = 1 << (s->spatial_decomposition_count - level);
 +                b->buf_x_offset = 0;
 +                b->buf_y_offset = 0;
 +
 +                if(orientation&1){
 +                    b->buf += (w+1)>>1;
 +                    b->buf_x_offset = (w+1)>>1;
 +                }
 +                if(orientation>1){
 +                    b->buf += b->stride>>1;
 +                    b->buf_y_offset = b->stride_line >> 1;
 +                }
 +                b->ibuf= s->spatial_idwt_buffer + (b->buf - s->spatial_dwt_buffer);
 +
 +                if(level)
 +                    b->parent= &s->plane[plane_index].band[level-1][orientation];
 +                //FIXME avoid this realloc
 +                av_freep(&b->x_coeff);
 +                b->x_coeff=av_mallocz_array(((b->width+1) * b->height+1), sizeof(x_and_coeff));
 +                if (!b->x_coeff)
 +                    goto fail;
 +            }
 +            w= (w+1)>>1;
 +            h= (h+1)>>1;
 +        }
 +    }
 +
 +    return 0;
 +fail:
 +    return AVERROR(ENOMEM);
 +}
 +
 +#define USE_HALFPEL_PLANE 0
 +
 +static int halfpel_interpol(SnowContext *s, uint8_t *halfpel[4][4], AVFrame *frame){
 +    int p,x,y;
 +
 +    for(p=0; p < s->nb_planes; p++){
 +        int is_chroma= !!p;
 +        int w= is_chroma ? s->avctx->width >>s->chroma_h_shift : s->avctx->width;
 +        int h= is_chroma ? s->avctx->height>>s->chroma_v_shift : s->avctx->height;
 +        int ls= frame->linesize[p];
 +        uint8_t *src= frame->data[p];
 +
 +        halfpel[1][p] = (uint8_t*) av_malloc(ls * (h + 2 * EDGE_WIDTH)) + EDGE_WIDTH * (1 + ls);
 +        halfpel[2][p] = (uint8_t*) av_malloc(ls * (h + 2 * EDGE_WIDTH)) + EDGE_WIDTH * (1 + ls);
 +        halfpel[3][p] = (uint8_t*) av_malloc(ls * (h + 2 * EDGE_WIDTH)) + EDGE_WIDTH * (1 + ls);
 +        if (!halfpel[1][p] || !halfpel[2][p] || !halfpel[3][p])
 +            return AVERROR(ENOMEM);
 +
 +        halfpel[0][p]= src;
 +        for(y=0; y<h; y++){
 +            for(x=0; x<w; x++){
 +                int i= y*ls + x;
 +
 +                halfpel[1][p][i]= (20*(src[i] + src[i+1]) - 5*(src[i-1] + src[i+2]) + (src[i-2] + src[i+3]) + 16 )>>5;
 +            }
 +        }
 +        for(y=0; y<h; y++){
 +            for(x=0; x<w; x++){
 +                int i= y*ls + x;
 +
 +                halfpel[2][p][i]= (20*(src[i] + src[i+ls]) - 5*(src[i-ls] + src[i+2*ls]) + (src[i-2*ls] + src[i+3*ls]) + 16 )>>5;
 +            }
 +        }
 +        src= halfpel[1][p];
 +        for(y=0; y<h; y++){
 +            for(x=0; x<w; x++){
 +                int i= y*ls + x;
 +
 +                halfpel[3][p][i]= (20*(src[i] + src[i+ls]) - 5*(src[i-ls] + src[i+2*ls]) + (src[i-2*ls] + src[i+3*ls]) + 16 )>>5;
 +            }
 +        }
 +
 +//FIXME border!
 +    }
 +    return 0;
 +}
 +
 +void ff_snow_release_buffer(AVCodecContext *avctx)
 +{
 +    SnowContext *s = avctx->priv_data;
 +    int i;
 +
 +    if(s->last_picture[s->max_ref_frames-1]->data[0]){
 +        av_frame_unref(s->last_picture[s->max_ref_frames-1]);
 +        for(i=0; i<9; i++)
 +            if(s->halfpel_plane[s->max_ref_frames-1][1+i/3][i%3])
 +                av_free(s->halfpel_plane[s->max_ref_frames-1][1+i/3][i%3] - EDGE_WIDTH*(1+s->current_picture->linesize[i%3]));
 +    }
 +}
 +
 +int ff_snow_frame_start(SnowContext *s){
 +   AVFrame *tmp;
 +   int i, ret;
 +
 +    ff_snow_release_buffer(s->avctx);
 +
 +    tmp= s->last_picture[s->max_ref_frames-1];
 +    for(i=s->max_ref_frames-1; i>0; i--)
 +        s->last_picture[i] = s->last_picture[i-1];
 +    memmove(s->halfpel_plane+1, s->halfpel_plane, (s->max_ref_frames-1)*sizeof(void*)*4*4);
 +    if(USE_HALFPEL_PLANE && s->current_picture->data[0]) {
 +        if((ret = halfpel_interpol(s, s->halfpel_plane[0], s->current_picture)) < 0)
 +            return ret;
 +    }
 +    s->last_picture[0] = s->current_picture;
 +    s->current_picture = tmp;
 +
 +    if(s->keyframe){
 +        s->ref_frames= 0;
 +    }else{
 +        int i;
 +        for(i=0; i<s->max_ref_frames && s->last_picture[i]->data[0]; i++)
 +            if(i && s->last_picture[i-1]->key_frame)
 +                break;
 +        s->ref_frames= i;
 +        if(s->ref_frames==0){
 +            av_log(s->avctx,AV_LOG_ERROR, "No reference frames\n");
 +            return -1;
 +        }
 +    }
 +    if ((ret = ff_snow_get_buffer(s, s->current_picture)) < 0)
 +        return ret;
 +
 +    s->current_picture->key_frame= s->keyframe;
 +
 +    return 0;
 +}
 +
 +av_cold void ff_snow_common_end(SnowContext *s)
 +{
 +    int plane_index, level, orientation, i;
 +
 +    av_freep(&s->spatial_dwt_buffer);
 +    av_freep(&s->temp_dwt_buffer);
 +    av_freep(&s->spatial_idwt_buffer);
 +    av_freep(&s->temp_idwt_buffer);
 +    av_freep(&s->run_buffer);
 +
 +    s->m.me.temp= NULL;
 +    av_freep(&s->m.me.scratchpad);
 +    av_freep(&s->m.me.map);
 +    av_freep(&s->m.me.score_map);
 +    av_freep(&s->m.obmc_scratchpad);
 +
 +    av_freep(&s->block);
 +    av_freep(&s->scratchbuf);
 +    av_freep(&s->emu_edge_buffer);
 +
 +    for(i=0; i<MAX_REF_FRAMES; i++){
 +        av_freep(&s->ref_mvs[i]);
 +        av_freep(&s->ref_scores[i]);
 +        if(s->last_picture[i]->data[0]) {
 +            av_assert0(s->last_picture[i]->data[0] != s->current_picture->data[0]);
 +        }
 +        av_frame_free(&s->last_picture[i]);
 +    }
 +
 +    for(plane_index=0; plane_index < s->nb_planes; plane_index++){
 +        for(level=s->spatial_decomposition_count-1; level>=0; level--){
 +            for(orientation=level ? 1 : 0; orientation<4; orientation++){
 +                SubBand *b= &s->plane[plane_index].band[level][orientation];
 +
 +                av_freep(&b->x_coeff);
 +            }
 +        }
 +    }
 +    av_frame_free(&s->mconly_picture);
 +    av_frame_free(&s->current_picture);
 +}
index 2cda5b3,0000000..38810c1
mode 100644,000000..100644
--- /dev/null
@@@ -1,710 -1,0 +1,710 @@@
- #include "dsputil.h"
 +/*
 + * Copyright (C) 2004 Michael Niedermayer <michaelni@gmx.at>
 + * Copyright (C) 2006 Robert Edele <yartrebo@earthlink.net>
 + *
 + * 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
 + */
 +
 +#ifndef AVCODEC_SNOW_H
 +#define AVCODEC_SNOW_H
 +
-     DSPContext dsp;
 +#include "hpeldsp.h"
++#include "me_cmp.h"
 +#include "qpeldsp.h"
 +#include "snow_dwt.h"
 +
 +#include "rangecoder.h"
 +#include "mathops.h"
 +#include "mpegvideo.h"
 +#include "h264qpel.h"
 +
 +#define MID_STATE 128
 +
 +#define MAX_PLANES 4
 +#define QSHIFT 5
 +#define QROOT (1<<QSHIFT)
 +#define LOSSLESS_QLOG -128
 +#define FRAC_BITS 4
 +#define MAX_REF_FRAMES 8
 +
 +#define LOG2_OBMC_MAX 8
 +#define OBMC_MAX (1<<(LOG2_OBMC_MAX))
 +typedef struct BlockNode{
 +    int16_t mx;
 +    int16_t my;
 +    uint8_t ref;
 +    uint8_t color[3];
 +    uint8_t type;
 +//#define TYPE_SPLIT    1
 +#define BLOCK_INTRA   1
 +#define BLOCK_OPT     2
 +//#define TYPE_NOCOLOR  4
 +    uint8_t level; //FIXME merge into type?
 +}BlockNode;
 +
 +static const BlockNode null_block= { //FIXME add border maybe
 +    .color= {128,128,128},
 +    .mx= 0,
 +    .my= 0,
 +    .ref= 0,
 +    .type= 0,
 +    .level= 0,
 +};
 +
 +#define LOG2_MB_SIZE 4
 +#define MB_SIZE (1<<LOG2_MB_SIZE)
 +#define ENCODER_EXTRA_BITS 4
 +#define HTAPS_MAX 8
 +
 +typedef struct x_and_coeff{
 +    int16_t x;
 +    uint16_t coeff;
 +} x_and_coeff;
 +
 +typedef struct SubBand{
 +    int level;
 +    int stride;
 +    int width;
 +    int height;
 +    int qlog;        ///< log(qscale)/log[2^(1/6)]
 +    DWTELEM *buf;
 +    IDWTELEM *ibuf;
 +    int buf_x_offset;
 +    int buf_y_offset;
 +    int stride_line; ///< Stride measured in lines, not pixels.
 +    x_and_coeff * x_coeff;
 +    struct SubBand *parent;
 +    uint8_t state[/*7*2*/ 7 + 512][32];
 +}SubBand;
 +
 +typedef struct Plane{
 +    int width;
 +    int height;
 +    SubBand band[MAX_DECOMPOSITIONS][4];
 +
 +    int htaps;
 +    int8_t hcoeff[HTAPS_MAX/2];
 +    int diag_mc;
 +    int fast_mc;
 +
 +    int last_htaps;
 +    int8_t last_hcoeff[HTAPS_MAX/2];
 +    int last_diag_mc;
 +}Plane;
 +
 +typedef struct SnowContext{
 +    AVClass *class;
 +    AVCodecContext *avctx;
 +    RangeCoder c;
++    MECmpContext mecc;
 +    HpelDSPContext hdsp;
 +    QpelDSPContext qdsp;
 +    VideoDSPContext vdsp;
 +    H264QpelContext h264qpel;
 +    MpegvideoEncDSPContext mpvencdsp;
 +    SnowDWTContext dwt;
 +    AVFrame *new_picture;
 +    AVFrame *input_picture;              ///< new_picture with the internal linesizes
 +    AVFrame *current_picture;
 +    AVFrame *last_picture[MAX_REF_FRAMES];
 +    uint8_t *halfpel_plane[MAX_REF_FRAMES][4][4];
 +    AVFrame *mconly_picture;
 +//     uint8_t q_context[16];
 +    uint8_t header_state[32];
 +    uint8_t block_state[128 + 32*128];
 +    int keyframe;
 +    int always_reset;
 +    int version;
 +    int spatial_decomposition_type;
 +    int last_spatial_decomposition_type;
 +    int temporal_decomposition_type;
 +    int spatial_decomposition_count;
 +    int last_spatial_decomposition_count;
 +    int temporal_decomposition_count;
 +    int max_ref_frames;
 +    int ref_frames;
 +    int16_t (*ref_mvs[MAX_REF_FRAMES])[2];
 +    uint32_t *ref_scores[MAX_REF_FRAMES];
 +    DWTELEM *spatial_dwt_buffer;
 +    DWTELEM *temp_dwt_buffer;
 +    IDWTELEM *spatial_idwt_buffer;
 +    IDWTELEM *temp_idwt_buffer;
 +    int *run_buffer;
 +    int colorspace_type;
 +    int chroma_h_shift;
 +    int chroma_v_shift;
 +    int spatial_scalability;
 +    int qlog;
 +    int last_qlog;
 +    int lambda;
 +    int lambda2;
 +    int pass1_rc;
 +    int mv_scale;
 +    int last_mv_scale;
 +    int qbias;
 +    int last_qbias;
 +#define QBIAS_SHIFT 3
 +    int b_width;
 +    int b_height;
 +    int block_max_depth;
 +    int last_block_max_depth;
 +    int nb_planes;
 +    Plane plane[MAX_PLANES];
 +    BlockNode *block;
 +#define ME_CACHE_SIZE 1024
 +    unsigned me_cache[ME_CACHE_SIZE];
 +    unsigned me_cache_generation;
 +    slice_buffer sb;
 +    int memc_only;
 +    int no_bitstream;
 +
 +    MpegEncContext m; // needed for motion estimation, should not be used for anything else, the idea is to eventually make the motion estimation independent of MpegEncContext, so this will be removed then (FIXME/XXX)
 +
 +    uint8_t *scratchbuf;
 +    uint8_t *emu_edge_buffer;
 +}SnowContext;
 +
 +/* Tables */
 +extern const uint8_t * const ff_obmc_tab[4];
 +extern uint8_t ff_qexp[QROOT];
 +extern int ff_scale_mv_ref[MAX_REF_FRAMES][MAX_REF_FRAMES];
 +
 +/* C bits used by mmx/sse2/altivec */
 +
 +static av_always_inline void snow_interleave_line_header(int * i, int width, IDWTELEM * low, IDWTELEM * high){
 +    (*i) = (width) - 2;
 +
 +    if (width & 1){
 +        low[(*i)+1] = low[((*i)+1)>>1];
 +        (*i)--;
 +    }
 +}
 +
 +static av_always_inline void snow_interleave_line_footer(int * i, IDWTELEM * low, IDWTELEM * high){
 +    for (; (*i)>=0; (*i)-=2){
 +        low[(*i)+1] = high[(*i)>>1];
 +        low[*i] = low[(*i)>>1];
 +    }
 +}
 +
 +static av_always_inline void snow_horizontal_compose_lift_lead_out(int i, IDWTELEM * dst, IDWTELEM * src, IDWTELEM * ref, int width, int w, int lift_high, int mul, int add, int shift){
 +    for(; i<w; i++){
 +        dst[i] = src[i] - ((mul * (ref[i] + ref[i + 1]) + add) >> shift);
 +    }
 +
 +    if((width^lift_high)&1){
 +        dst[w] = src[w] - ((mul * 2 * ref[w] + add) >> shift);
 +    }
 +}
 +
 +static av_always_inline void snow_horizontal_compose_liftS_lead_out(int i, IDWTELEM * dst, IDWTELEM * src, IDWTELEM * ref, int width, int w){
 +        for(; i<w; i++){
 +            dst[i] = src[i] + ((ref[i] + ref[(i+1)]+W_BO + 4 * src[i]) >> W_BS);
 +        }
 +
 +        if(width&1){
 +            dst[w] = src[w] + ((2 * ref[w] + W_BO + 4 * src[w]) >> W_BS);
 +        }
 +}
 +
 +/* common code */
 +
 +int ff_snow_common_init(AVCodecContext *avctx);
 +int ff_snow_common_init_after_header(AVCodecContext *avctx);
 +void ff_snow_common_end(SnowContext *s);
 +void ff_snow_release_buffer(AVCodecContext *avctx);
 +void ff_snow_reset_contexts(SnowContext *s);
 +int ff_snow_alloc_blocks(SnowContext *s);
 +int ff_snow_frame_start(SnowContext *s);
 +void ff_snow_pred_block(SnowContext *s, uint8_t *dst, uint8_t *tmp, ptrdiff_t stride,
 +                     int sx, int sy, int b_w, int b_h, BlockNode *block,
 +                     int plane_index, int w, int h);
 +int ff_snow_get_buffer(SnowContext *s, AVFrame *frame);
 +/* common inline functions */
 +//XXX doublecheck all of them should stay inlined
 +
 +static inline void snow_set_blocks(SnowContext *s, int level, int x, int y, int l, int cb, int cr, int mx, int my, int ref, int type){
 +    const int w= s->b_width << s->block_max_depth;
 +    const int rem_depth= s->block_max_depth - level;
 +    const int index= (x + y*w) << rem_depth;
 +    const int block_w= 1<<rem_depth;
 +    BlockNode block;
 +    int i,j;
 +
 +    block.color[0]= l;
 +    block.color[1]= cb;
 +    block.color[2]= cr;
 +    block.mx= mx;
 +    block.my= my;
 +    block.ref= ref;
 +    block.type= type;
 +    block.level= level;
 +
 +    for(j=0; j<block_w; j++){
 +        for(i=0; i<block_w; i++){
 +            s->block[index + i + j*w]= block;
 +        }
 +    }
 +}
 +
 +static inline void pred_mv(SnowContext *s, int *mx, int *my, int ref,
 +                           const BlockNode *left, const BlockNode *top, const BlockNode *tr){
 +    if(s->ref_frames == 1){
 +        *mx = mid_pred(left->mx, top->mx, tr->mx);
 +        *my = mid_pred(left->my, top->my, tr->my);
 +    }else{
 +        const int *scale = ff_scale_mv_ref[ref];
 +        *mx = mid_pred((left->mx * scale[left->ref] + 128) >>8,
 +                       (top ->mx * scale[top ->ref] + 128) >>8,
 +                       (tr  ->mx * scale[tr  ->ref] + 128) >>8);
 +        *my = mid_pred((left->my * scale[left->ref] + 128) >>8,
 +                       (top ->my * scale[top ->ref] + 128) >>8,
 +                       (tr  ->my * scale[tr  ->ref] + 128) >>8);
 +    }
 +}
 +
 +static av_always_inline int same_block(BlockNode *a, BlockNode *b){
 +    if((a->type&BLOCK_INTRA) && (b->type&BLOCK_INTRA)){
 +        return !((a->color[0] - b->color[0]) | (a->color[1] - b->color[1]) | (a->color[2] - b->color[2]));
 +    }else{
 +        return !((a->mx - b->mx) | (a->my - b->my) | (a->ref - b->ref) | ((a->type ^ b->type)&BLOCK_INTRA));
 +    }
 +}
 +
 +//FIXME name cleanup (b_w, block_w, b_width stuff)
 +//XXX should we really inline it?
 +static av_always_inline void add_yblock(SnowContext *s, int sliced, slice_buffer *sb, IDWTELEM *dst, uint8_t *dst8, const uint8_t *obmc, int src_x, int src_y, int b_w, int b_h, int w, int h, int dst_stride, int src_stride, int obmc_stride, int b_x, int b_y, int add, int offset_dst, int plane_index){
 +    const int b_width = s->b_width  << s->block_max_depth;
 +    const int b_height= s->b_height << s->block_max_depth;
 +    const int b_stride= b_width;
 +    BlockNode *lt= &s->block[b_x + b_y*b_stride];
 +    BlockNode *rt= lt+1;
 +    BlockNode *lb= lt+b_stride;
 +    BlockNode *rb= lb+1;
 +    uint8_t *block[4];
 +    int tmp_step= src_stride >= 7*MB_SIZE ? MB_SIZE : MB_SIZE*src_stride;
 +    uint8_t *tmp = s->scratchbuf;
 +    uint8_t *ptmp;
 +    int x,y;
 +
 +    if(b_x<0){
 +        lt= rt;
 +        lb= rb;
 +    }else if(b_x + 1 >= b_width){
 +        rt= lt;
 +        rb= lb;
 +    }
 +    if(b_y<0){
 +        lt= lb;
 +        rt= rb;
 +    }else if(b_y + 1 >= b_height){
 +        lb= lt;
 +        rb= rt;
 +    }
 +
 +    if(src_x<0){ //FIXME merge with prev & always round internal width up to *16
 +        obmc -= src_x;
 +        b_w += src_x;
 +        if(!sliced && !offset_dst)
 +            dst -= src_x;
 +        src_x=0;
 +    }
 +    if(src_x + b_w > w){
 +        b_w = w - src_x;
 +    }
 +    if(src_y<0){
 +        obmc -= src_y*obmc_stride;
 +        b_h += src_y;
 +        if(!sliced && !offset_dst)
 +            dst -= src_y*dst_stride;
 +        src_y=0;
 +    }
 +    if(src_y + b_h> h){
 +        b_h = h - src_y;
 +    }
 +
 +    if(b_w<=0 || b_h<=0) return;
 +
 +    av_assert2(src_stride > 2*MB_SIZE + 5);
 +
 +    if(!sliced && offset_dst)
 +        dst += src_x + src_y*dst_stride;
 +    dst8+= src_x + src_y*src_stride;
 +//    src += src_x + src_y*src_stride;
 +
 +    ptmp= tmp + 3*tmp_step;
 +    block[0]= ptmp;
 +    ptmp+=tmp_step;
 +    ff_snow_pred_block(s, block[0], tmp, src_stride, src_x, src_y, b_w, b_h, lt, plane_index, w, h);
 +
 +    if(same_block(lt, rt)){
 +        block[1]= block[0];
 +    }else{
 +        block[1]= ptmp;
 +        ptmp+=tmp_step;
 +        ff_snow_pred_block(s, block[1], tmp, src_stride, src_x, src_y, b_w, b_h, rt, plane_index, w, h);
 +    }
 +
 +    if(same_block(lt, lb)){
 +        block[2]= block[0];
 +    }else if(same_block(rt, lb)){
 +        block[2]= block[1];
 +    }else{
 +        block[2]= ptmp;
 +        ptmp+=tmp_step;
 +        ff_snow_pred_block(s, block[2], tmp, src_stride, src_x, src_y, b_w, b_h, lb, plane_index, w, h);
 +    }
 +
 +    if(same_block(lt, rb) ){
 +        block[3]= block[0];
 +    }else if(same_block(rt, rb)){
 +        block[3]= block[1];
 +    }else if(same_block(lb, rb)){
 +        block[3]= block[2];
 +    }else{
 +        block[3]= ptmp;
 +        ff_snow_pred_block(s, block[3], tmp, src_stride, src_x, src_y, b_w, b_h, rb, plane_index, w, h);
 +    }
 +    if(sliced){
 +        s->dwt.inner_add_yblock(obmc, obmc_stride, block, b_w, b_h, src_x,src_y, src_stride, sb, add, dst8);
 +    }else{
 +        for(y=0; y<b_h; y++){
 +            //FIXME ugly misuse of obmc_stride
 +            const uint8_t *obmc1= obmc + y*obmc_stride;
 +            const uint8_t *obmc2= obmc1+ (obmc_stride>>1);
 +            const uint8_t *obmc3= obmc1+ obmc_stride*(obmc_stride>>1);
 +            const uint8_t *obmc4= obmc3+ (obmc_stride>>1);
 +            for(x=0; x<b_w; x++){
 +                int v=   obmc1[x] * block[3][x + y*src_stride]
 +                        +obmc2[x] * block[2][x + y*src_stride]
 +                        +obmc3[x] * block[1][x + y*src_stride]
 +                        +obmc4[x] * block[0][x + y*src_stride];
 +
 +                v <<= 8 - LOG2_OBMC_MAX;
 +                if(FRAC_BITS != 8){
 +                    v >>= 8 - FRAC_BITS;
 +                }
 +                if(add){
 +                    v += dst[x + y*dst_stride];
 +                    v = (v + (1<<(FRAC_BITS-1))) >> FRAC_BITS;
 +                    if(v&(~255)) v= ~(v>>31);
 +                    dst8[x + y*src_stride] = v;
 +                }else{
 +                    dst[x + y*dst_stride] -= v;
 +                }
 +            }
 +        }
 +    }
 +}
 +
 +static av_always_inline void predict_slice(SnowContext *s, IDWTELEM *buf, int plane_index, int add, int mb_y){
 +    Plane *p= &s->plane[plane_index];
 +    const int mb_w= s->b_width  << s->block_max_depth;
 +    const int mb_h= s->b_height << s->block_max_depth;
 +    int x, y, mb_x;
 +    int block_size = MB_SIZE >> s->block_max_depth;
 +    int block_w    = plane_index ? block_size>>s->chroma_h_shift : block_size;
 +    int block_h    = plane_index ? block_size>>s->chroma_v_shift : block_size;
 +    const uint8_t *obmc  = plane_index ? ff_obmc_tab[s->block_max_depth+s->chroma_h_shift] : ff_obmc_tab[s->block_max_depth];
 +    const int obmc_stride= plane_index ? (2*block_size)>>s->chroma_h_shift : 2*block_size;
 +    int ref_stride= s->current_picture->linesize[plane_index];
 +    uint8_t *dst8= s->current_picture->data[plane_index];
 +    int w= p->width;
 +    int h= p->height;
 +    av_assert2(s->chroma_h_shift == s->chroma_v_shift); // obmc params assume squares
 +    if(s->keyframe || (s->avctx->debug&512)){
 +        if(mb_y==mb_h)
 +            return;
 +
 +        if(add){
 +            for(y=block_h*mb_y; y<FFMIN(h,block_h*(mb_y+1)); y++){
 +                for(x=0; x<w; x++){
 +                    int v= buf[x + y*w] + (128<<FRAC_BITS) + (1<<(FRAC_BITS-1));
 +                    v >>= FRAC_BITS;
 +                    if(v&(~255)) v= ~(v>>31);
 +                    dst8[x + y*ref_stride]= v;
 +                }
 +            }
 +        }else{
 +            for(y=block_h*mb_y; y<FFMIN(h,block_h*(mb_y+1)); y++){
 +                for(x=0; x<w; x++){
 +                    buf[x + y*w]-= 128<<FRAC_BITS;
 +                }
 +            }
 +        }
 +
 +        return;
 +    }
 +
 +    for(mb_x=0; mb_x<=mb_w; mb_x++){
 +        add_yblock(s, 0, NULL, buf, dst8, obmc,
 +                   block_w*mb_x - block_w/2,
 +                   block_h*mb_y - block_h/2,
 +                   block_w, block_h,
 +                   w, h,
 +                   w, ref_stride, obmc_stride,
 +                   mb_x - 1, mb_y - 1,
 +                   add, 1, plane_index);
 +    }
 +}
 +
 +static av_always_inline void predict_plane(SnowContext *s, IDWTELEM *buf, int plane_index, int add){
 +    const int mb_h= s->b_height << s->block_max_depth;
 +    int mb_y;
 +    for(mb_y=0; mb_y<=mb_h; mb_y++)
 +        predict_slice(s, buf, plane_index, add, mb_y);
 +}
 +
 +static inline void set_blocks(SnowContext *s, int level, int x, int y, int l, int cb, int cr, int mx, int my, int ref, int type){
 +    const int w= s->b_width << s->block_max_depth;
 +    const int rem_depth= s->block_max_depth - level;
 +    const int index= (x + y*w) << rem_depth;
 +    const int block_w= 1<<rem_depth;
 +    const int block_h= 1<<rem_depth; //FIXME "w!=h"
 +    BlockNode block;
 +    int i,j;
 +
 +    block.color[0]= l;
 +    block.color[1]= cb;
 +    block.color[2]= cr;
 +    block.mx= mx;
 +    block.my= my;
 +    block.ref= ref;
 +    block.type= type;
 +    block.level= level;
 +
 +    for(j=0; j<block_h; j++){
 +        for(i=0; i<block_w; i++){
 +            s->block[index + i + j*w]= block;
 +        }
 +    }
 +}
 +
 +static inline void init_ref(MotionEstContext *c, uint8_t *src[3], uint8_t *ref[3], uint8_t *ref2[3], int x, int y, int ref_index){
 +    SnowContext *s = c->avctx->priv_data;
 +    const int offset[3]= {
 +          y*c->  stride + x,
 +        ((y*c->uvstride + x)>>s->chroma_h_shift),
 +        ((y*c->uvstride + x)>>s->chroma_h_shift),
 +    };
 +    int i;
 +    for(i=0; i<3; i++){
 +        c->src[0][i]= src [i];
 +        c->ref[0][i]= ref [i] + offset[i];
 +    }
 +    av_assert2(!ref_index);
 +}
 +
 +
 +/* bitstream functions */
 +
 +extern const int8_t ff_quant3bA[256];
 +
 +#define QEXPSHIFT (7-FRAC_BITS+8) //FIXME try to change this to 0
 +
 +static inline void put_symbol(RangeCoder *c, uint8_t *state, int v, int is_signed){
 +    int i;
 +
 +    if(v){
 +        const int a= FFABS(v);
 +        const int e= av_log2(a);
 +        const int el= FFMIN(e, 10);
 +        put_rac(c, state+0, 0);
 +
 +        for(i=0; i<el; i++){
 +            put_rac(c, state+1+i, 1);  //1..10
 +        }
 +        for(; i<e; i++){
 +            put_rac(c, state+1+9, 1);  //1..10
 +        }
 +        put_rac(c, state+1+FFMIN(i,9), 0);
 +
 +        for(i=e-1; i>=el; i--){
 +            put_rac(c, state+22+9, (a>>i)&1); //22..31
 +        }
 +        for(; i>=0; i--){
 +            put_rac(c, state+22+i, (a>>i)&1); //22..31
 +        }
 +
 +        if(is_signed)
 +            put_rac(c, state+11 + el, v < 0); //11..21
 +    }else{
 +        put_rac(c, state+0, 1);
 +    }
 +}
 +
 +static inline int get_symbol(RangeCoder *c, uint8_t *state, int is_signed){
 +    if(get_rac(c, state+0))
 +        return 0;
 +    else{
 +        int i, e, a;
 +        e= 0;
 +        while(get_rac(c, state+1 + FFMIN(e,9))){ //1..10
 +            e++;
 +        }
 +
 +        a= 1;
 +        for(i=e-1; i>=0; i--){
 +            a += a + get_rac(c, state+22 + FFMIN(i,9)); //22..31
 +        }
 +
 +        e= -(is_signed && get_rac(c, state+11 + FFMIN(e,10))); //11..21
 +        return (a^e)-e;
 +    }
 +}
 +
 +static inline void put_symbol2(RangeCoder *c, uint8_t *state, int v, int log2){
 +    int i;
 +    int r= log2>=0 ? 1<<log2 : 1;
 +
 +    av_assert2(v>=0);
 +    av_assert2(log2>=-4);
 +
 +    while(v >= r){
 +        put_rac(c, state+4+log2, 1);
 +        v -= r;
 +        log2++;
 +        if(log2>0) r+=r;
 +    }
 +    put_rac(c, state+4+log2, 0);
 +
 +    for(i=log2-1; i>=0; i--){
 +        put_rac(c, state+31-i, (v>>i)&1);
 +    }
 +}
 +
 +static inline int get_symbol2(RangeCoder *c, uint8_t *state, int log2){
 +    int i;
 +    int r= log2>=0 ? 1<<log2 : 1;
 +    int v=0;
 +
 +    av_assert2(log2>=-4);
 +
 +    while(log2<28 && get_rac(c, state+4+log2)){
 +        v+= r;
 +        log2++;
 +        if(log2>0) r+=r;
 +    }
 +
 +    for(i=log2-1; i>=0; i--){
 +        v+= get_rac(c, state+31-i)<<i;
 +    }
 +
 +    return v;
 +}
 +
 +static inline void unpack_coeffs(SnowContext *s, SubBand *b, SubBand * parent, int orientation){
 +    const int w= b->width;
 +    const int h= b->height;
 +    int x,y;
 +
 +    int run, runs;
 +    x_and_coeff *xc= b->x_coeff;
 +    x_and_coeff *prev_xc= NULL;
 +    x_and_coeff *prev2_xc= xc;
 +    x_and_coeff *parent_xc= parent ? parent->x_coeff : NULL;
 +    x_and_coeff *prev_parent_xc= parent_xc;
 +
 +    runs= get_symbol2(&s->c, b->state[30], 0);
 +    if(runs-- > 0) run= get_symbol2(&s->c, b->state[1], 3);
 +    else           run= INT_MAX;
 +
 +    for(y=0; y<h; y++){
 +        int v=0;
 +        int lt=0, t=0, rt=0;
 +
 +        if(y && prev_xc->x == 0){
 +            rt= prev_xc->coeff;
 +        }
 +        for(x=0; x<w; x++){
 +            int p=0;
 +            const int l= v;
 +
 +            lt= t; t= rt;
 +
 +            if(y){
 +                if(prev_xc->x <= x)
 +                    prev_xc++;
 +                if(prev_xc->x == x + 1)
 +                    rt= prev_xc->coeff;
 +                else
 +                    rt=0;
 +            }
 +            if(parent_xc){
 +                if(x>>1 > parent_xc->x){
 +                    parent_xc++;
 +                }
 +                if(x>>1 == parent_xc->x){
 +                    p= parent_xc->coeff;
 +                }
 +            }
 +            if(/*ll|*/l|lt|t|rt|p){
 +                int context= av_log2(/*FFABS(ll) + */3*(l>>1) + (lt>>1) + (t&~1) + (rt>>1) + (p>>1));
 +
 +                v=get_rac(&s->c, &b->state[0][context]);
 +                if(v){
 +                    v= 2*(get_symbol2(&s->c, b->state[context + 2], context-4) + 1);
 +                    v+=get_rac(&s->c, &b->state[0][16 + 1 + 3 + ff_quant3bA[l&0xFF] + 3*ff_quant3bA[t&0xFF]]);
 +
 +                    xc->x=x;
 +                    (xc++)->coeff= v;
 +                }
 +            }else{
 +                if(!run){
 +                    if(runs-- > 0) run= get_symbol2(&s->c, b->state[1], 3);
 +                    else           run= INT_MAX;
 +                    v= 2*(get_symbol2(&s->c, b->state[0 + 2], 0-4) + 1);
 +                    v+=get_rac(&s->c, &b->state[0][16 + 1 + 3]);
 +
 +                    xc->x=x;
 +                    (xc++)->coeff= v;
 +                }else{
 +                    int max_run;
 +                    run--;
 +                    v=0;
 +                    av_assert2(run >= 0);
 +                    if(y) max_run= FFMIN(run, prev_xc->x - x - 2);
 +                    else  max_run= FFMIN(run, w-x-1);
 +                    if(parent_xc)
 +                        max_run= FFMIN(max_run, 2*parent_xc->x - x - 1);
 +                    av_assert2(max_run >= 0 && max_run <= run);
 +
 +                    x+= max_run;
 +                    run-= max_run;
 +                }
 +            }
 +        }
 +        (xc++)->x= w+1; //end marker
 +        prev_xc= prev2_xc;
 +        prev2_xc= xc;
 +
 +        if(parent_xc){
 +            if(y&1){
 +                while(parent_xc->x != parent->width+1)
 +                    parent_xc++;
 +                parent_xc++;
 +                prev_parent_xc= parent_xc;
 +            }else{
 +                parent_xc= prev_parent_xc;
 +            }
 +        }
 +    }
 +
 +    (xc++)->x= w+1; //end marker
 +}
 +
 +#endif /* AVCODEC_SNOW_H */
index cd94c13,0000000..63ff7a0
mode 100644,000000..100644
--- /dev/null
@@@ -1,865 -1,0 +1,865 @@@
- #include "dsputil.h"
 +/*
 + * Copyright (C) 2004-2010 Michael Niedermayer <michaelni@gmx.at>
 + * Copyright (C) 2008 David Conrad
 + *
 + * 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
 + */
 +
 +#include "libavutil/attributes.h"
 +#include "libavutil/avassert.h"
 +#include "libavutil/common.h"
- void ff_dsputil_init_dwt(DSPContext *c)
++#include "me_cmp.h"
 +#include "snow_dwt.h"
 +
 +int ff_slice_buffer_init(slice_buffer *buf, int line_count,
 +                         int max_allocated_lines, int line_width,
 +                         IDWTELEM *base_buffer)
 +{
 +    int i;
 +
 +    buf->base_buffer = base_buffer;
 +    buf->line_count  = line_count;
 +    buf->line_width  = line_width;
 +    buf->data_count  = max_allocated_lines;
 +    buf->line        = av_mallocz_array(line_count, sizeof(IDWTELEM *));
 +    if (!buf->line)
 +        return AVERROR(ENOMEM);
 +    buf->data_stack  = av_malloc_array(max_allocated_lines, sizeof(IDWTELEM *));
 +    if (!buf->data_stack) {
 +        av_freep(&buf->line);
 +        return AVERROR(ENOMEM);
 +    }
 +
 +    for (i = 0; i < max_allocated_lines; i++) {
 +        buf->data_stack[i] = av_malloc_array(line_width, sizeof(IDWTELEM));
 +        if (!buf->data_stack[i]) {
 +            for (i--; i >=0; i--)
 +                av_freep(&buf->data_stack[i]);
 +            av_freep(&buf->data_stack);
 +            av_freep(&buf->line);
 +            return AVERROR(ENOMEM);
 +        }
 +    }
 +
 +    buf->data_stack_top = max_allocated_lines - 1;
 +    return 0;
 +}
 +
 +IDWTELEM *ff_slice_buffer_load_line(slice_buffer *buf, int line)
 +{
 +    IDWTELEM *buffer;
 +
 +    av_assert0(buf->data_stack_top >= 0);
 +//  av_assert1(!buf->line[line]);
 +    if (buf->line[line])
 +        return buf->line[line];
 +
 +    buffer = buf->data_stack[buf->data_stack_top];
 +    buf->data_stack_top--;
 +    buf->line[line] = buffer;
 +
 +    return buffer;
 +}
 +
 +void ff_slice_buffer_release(slice_buffer *buf, int line)
 +{
 +    IDWTELEM *buffer;
 +
 +    av_assert1(line >= 0 && line < buf->line_count);
 +    av_assert1(buf->line[line]);
 +
 +    buffer = buf->line[line];
 +    buf->data_stack_top++;
 +    buf->data_stack[buf->data_stack_top] = buffer;
 +    buf->line[line]                      = NULL;
 +}
 +
 +void ff_slice_buffer_flush(slice_buffer *buf)
 +{
 +    int i;
 +    for (i = 0; i < buf->line_count; i++)
 +        if (buf->line[i])
 +            ff_slice_buffer_release(buf, i);
 +}
 +
 +void ff_slice_buffer_destroy(slice_buffer *buf)
 +{
 +    int i;
 +    ff_slice_buffer_flush(buf);
 +
 +    for (i = buf->data_count - 1; i >= 0; i--)
 +        av_freep(&buf->data_stack[i]);
 +    av_freep(&buf->data_stack);
 +    av_freep(&buf->line);
 +}
 +
 +static inline int mirror(int v, int m)
 +{
 +    while ((unsigned)v > (unsigned)m) {
 +        v = -v;
 +        if (v < 0)
 +            v += 2 * m;
 +    }
 +    return v;
 +}
 +
 +static av_always_inline void lift(DWTELEM *dst, DWTELEM *src, DWTELEM *ref,
 +                                  int dst_step, int src_step, int ref_step,
 +                                  int width, int mul, int add, int shift,
 +                                  int highpass, int inverse)
 +{
 +    const int mirror_left  = !highpass;
 +    const int mirror_right = (width & 1) ^ highpass;
 +    const int w            = (width >> 1) - 1 + (highpass & width);
 +    int i;
 +
 +#define LIFT(src, ref, inv) ((src) + ((inv) ? -(ref) : +(ref)))
 +    if (mirror_left) {
 +        dst[0] = LIFT(src[0], ((mul * 2 * ref[0] + add) >> shift), inverse);
 +        dst   += dst_step;
 +        src   += src_step;
 +    }
 +
 +    for (i = 0; i < w; i++)
 +        dst[i * dst_step] = LIFT(src[i * src_step],
 +                                 ((mul * (ref[i * ref_step] +
 +                                          ref[(i + 1) * ref_step]) +
 +                                   add) >> shift),
 +                                 inverse);
 +
 +    if (mirror_right)
 +        dst[w * dst_step] = LIFT(src[w * src_step],
 +                                 ((mul * 2 * ref[w * ref_step] + add) >> shift),
 +                                 inverse);
 +}
 +
 +static av_always_inline void liftS(DWTELEM *dst, DWTELEM *src, DWTELEM *ref,
 +                                   int dst_step, int src_step, int ref_step,
 +                                   int width, int mul, int add, int shift,
 +                                   int highpass, int inverse)
 +{
 +    const int mirror_left  = !highpass;
 +    const int mirror_right = (width & 1) ^ highpass;
 +    const int w            = (width >> 1) - 1 + (highpass & width);
 +    int i;
 +
 +    av_assert1(shift == 4);
 +#define LIFTS(src, ref, inv)                                            \
 +    ((inv) ? (src) + (((ref) + 4 * (src)) >> shift)                     \
 +           : -((-16 * (src) + (ref) + add /                             \
 +                4 + 1 + (5 << 25)) / (5 * 4) - (1 << 23)))
 +    if (mirror_left) {
 +        dst[0] = LIFTS(src[0], mul * 2 * ref[0] + add, inverse);
 +        dst   += dst_step;
 +        src   += src_step;
 +    }
 +
 +    for (i = 0; i < w; i++)
 +        dst[i * dst_step] = LIFTS(src[i * src_step],
 +                                  mul * (ref[i * ref_step] +
 +                                         ref[(i + 1) * ref_step]) + add,
 +                                  inverse);
 +
 +    if (mirror_right)
 +        dst[w * dst_step] = LIFTS(src[w * src_step],
 +                                  mul * 2 * ref[w * ref_step] + add,
 +                                  inverse);
 +}
 +
 +static void horizontal_decompose53i(DWTELEM *b, DWTELEM *temp, int width)
 +{
 +    const int width2 = width >> 1;
 +    int x;
 +    const int w2 = (width + 1) >> 1;
 +
 +    for (x = 0; x < width2; x++) {
 +        temp[x]      = b[2 * x];
 +        temp[x + w2] = b[2 * x + 1];
 +    }
 +    if (width & 1)
 +        temp[x] = b[2 * x];
 +    lift(b + w2, temp + w2, temp,   1, 1, 1, width, -1, 0, 1, 1, 0);
 +    lift(b,      temp,      b + w2, 1, 1, 1, width,  1, 2, 2, 0, 0);
 +}
 +
 +static void vertical_decompose53iH0(DWTELEM *b0, DWTELEM *b1, DWTELEM *b2,
 +                                    int width)
 +{
 +    int i;
 +
 +    for (i = 0; i < width; i++)
 +        b1[i] -= (b0[i] + b2[i]) >> 1;
 +}
 +
 +static void vertical_decompose53iL0(DWTELEM *b0, DWTELEM *b1, DWTELEM *b2,
 +                                    int width)
 +{
 +    int i;
 +
 +    for (i = 0; i < width; i++)
 +        b1[i] += (b0[i] + b2[i] + 2) >> 2;
 +}
 +
 +static void spatial_decompose53i(DWTELEM *buffer, DWTELEM *temp,
 +                                 int width, int height, int stride)
 +{
 +    int y;
 +    DWTELEM *b0 = buffer + mirror(-2 - 1, height - 1) * stride;
 +    DWTELEM *b1 = buffer + mirror(-2,     height - 1) * stride;
 +
 +    for (y = -2; y < height; y += 2) {
 +        DWTELEM *b2 = buffer + mirror(y + 1, height - 1) * stride;
 +        DWTELEM *b3 = buffer + mirror(y + 2, height - 1) * stride;
 +
 +        if (y + 1 < (unsigned)height)
 +            horizontal_decompose53i(b2, temp, width);
 +        if (y + 2 < (unsigned)height)
 +            horizontal_decompose53i(b3, temp, width);
 +
 +        if (y + 1 < (unsigned)height)
 +            vertical_decompose53iH0(b1, b2, b3, width);
 +        if (y + 0 < (unsigned)height)
 +            vertical_decompose53iL0(b0, b1, b2, width);
 +
 +        b0 = b2;
 +        b1 = b3;
 +    }
 +}
 +
 +static void horizontal_decompose97i(DWTELEM *b, DWTELEM *temp, int width)
 +{
 +    const int w2 = (width + 1) >> 1;
 +
 +    lift(temp + w2, b + 1, b,         1, 2, 2, width, W_AM, W_AO, W_AS, 1, 1);
 +    liftS(temp,     b,     temp + w2, 1, 2, 1, width, W_BM, W_BO, W_BS, 0, 0);
 +    lift(b + w2, temp + w2, temp,     1, 1, 1, width, W_CM, W_CO, W_CS, 1, 0);
 +    lift(b,      temp,      b + w2,   1, 1, 1, width, W_DM, W_DO, W_DS, 0, 0);
 +}
 +
 +static void vertical_decompose97iH0(DWTELEM *b0, DWTELEM *b1, DWTELEM *b2,
 +                                    int width)
 +{
 +    int i;
 +
 +    for (i = 0; i < width; i++)
 +        b1[i] -= (W_AM * (b0[i] + b2[i]) + W_AO) >> W_AS;
 +}
 +
 +static void vertical_decompose97iH1(DWTELEM *b0, DWTELEM *b1, DWTELEM *b2,
 +                                    int width)
 +{
 +    int i;
 +
 +    for (i = 0; i < width; i++)
 +        b1[i] += (W_CM * (b0[i] + b2[i]) + W_CO) >> W_CS;
 +}
 +
 +static void vertical_decompose97iL0(DWTELEM *b0, DWTELEM *b1, DWTELEM *b2,
 +                                    int width)
 +{
 +    int i;
 +
 +    for (i = 0; i < width; i++)
 +        b1[i] = (16 * 4 * b1[i] - 4 * (b0[i] + b2[i]) + W_BO * 5 + (5 << 27)) /
 +                (5 * 16) - (1 << 23);
 +}
 +
 +static void vertical_decompose97iL1(DWTELEM *b0, DWTELEM *b1, DWTELEM *b2,
 +                                    int width)
 +{
 +    int i;
 +
 +    for (i = 0; i < width; i++)
 +        b1[i] += (W_DM * (b0[i] + b2[i]) + W_DO) >> W_DS;
 +}
 +
 +static void spatial_decompose97i(DWTELEM *buffer, DWTELEM *temp,
 +                                 int width, int height, int stride)
 +{
 +    int y;
 +    DWTELEM *b0 = buffer + mirror(-4 - 1, height - 1) * stride;
 +    DWTELEM *b1 = buffer + mirror(-4,     height - 1) * stride;
 +    DWTELEM *b2 = buffer + mirror(-4 + 1, height - 1) * stride;
 +    DWTELEM *b3 = buffer + mirror(-4 + 2, height - 1) * stride;
 +
 +    for (y = -4; y < height; y += 2) {
 +        DWTELEM *b4 = buffer + mirror(y + 3, height - 1) * stride;
 +        DWTELEM *b5 = buffer + mirror(y + 4, height - 1) * stride;
 +
 +        if (y + 3 < (unsigned)height)
 +            horizontal_decompose97i(b4, temp, width);
 +        if (y + 4 < (unsigned)height)
 +            horizontal_decompose97i(b5, temp, width);
 +
 +        if (y + 3 < (unsigned)height)
 +            vertical_decompose97iH0(b3, b4, b5, width);
 +        if (y + 2 < (unsigned)height)
 +            vertical_decompose97iL0(b2, b3, b4, width);
 +        if (y + 1 < (unsigned)height)
 +            vertical_decompose97iH1(b1, b2, b3, width);
 +        if (y + 0 < (unsigned)height)
 +            vertical_decompose97iL1(b0, b1, b2, width);
 +
 +        b0 = b2;
 +        b1 = b3;
 +        b2 = b4;
 +        b3 = b5;
 +    }
 +}
 +
 +void ff_spatial_dwt(DWTELEM *buffer, DWTELEM *temp, int width, int height,
 +                    int stride, int type, int decomposition_count)
 +{
 +    int level;
 +
 +    for (level = 0; level < decomposition_count; level++) {
 +        switch (type) {
 +        case DWT_97:
 +            spatial_decompose97i(buffer, temp,
 +                                 width >> level, height >> level,
 +                                 stride << level);
 +            break;
 +        case DWT_53:
 +            spatial_decompose53i(buffer, temp,
 +                                 width >> level, height >> level,
 +                                 stride << level);
 +            break;
 +        }
 +    }
 +}
 +
 +static void horizontal_compose53i(IDWTELEM *b, IDWTELEM *temp, int width)
 +{
 +    const int width2 = width >> 1;
 +    const int w2     = (width + 1) >> 1;
 +    int x;
 +
 +    for (x = 0; x < width2; x++) {
 +        temp[2 * x]     = b[x];
 +        temp[2 * x + 1] = b[x + w2];
 +    }
 +    if (width & 1)
 +        temp[2 * x] = b[x];
 +
 +    b[0] = temp[0] - ((temp[1] + 1) >> 1);
 +    for (x = 2; x < width - 1; x += 2) {
 +        b[x]     = temp[x]     - ((temp[x - 1] + temp[x + 1] + 2) >> 2);
 +        b[x - 1] = temp[x - 1] + ((b[x - 2]    + b[x]        + 1) >> 1);
 +    }
 +    if (width & 1) {
 +        b[x]     = temp[x]     - ((temp[x - 1]     + 1) >> 1);
 +        b[x - 1] = temp[x - 1] + ((b[x - 2] + b[x] + 1) >> 1);
 +    } else
 +        b[x - 1] = temp[x - 1] + b[x - 2];
 +}
 +
 +static void vertical_compose53iH0(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2,
 +                                  int width)
 +{
 +    int i;
 +
 +    for (i = 0; i < width; i++)
 +        b1[i] += (b0[i] + b2[i]) >> 1;
 +}
 +
 +static void vertical_compose53iL0(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2,
 +                                  int width)
 +{
 +    int i;
 +
 +    for (i = 0; i < width; i++)
 +        b1[i] -= (b0[i] + b2[i] + 2) >> 2;
 +}
 +
 +static void spatial_compose53i_buffered_init(DWTCompose *cs, slice_buffer *sb,
 +                                             int height, int stride_line)
 +{
 +    cs->b0 = slice_buffer_get_line(sb,
 +                                   mirror(-1 - 1, height - 1) * stride_line);
 +    cs->b1 = slice_buffer_get_line(sb, mirror(-1, height - 1) * stride_line);
 +    cs->y  = -1;
 +}
 +
 +static void spatial_compose53i_init(DWTCompose *cs, IDWTELEM *buffer,
 +                                    int height, int stride)
 +{
 +    cs->b0 = buffer + mirror(-1 - 1, height - 1) * stride;
 +    cs->b1 = buffer + mirror(-1,     height - 1) * stride;
 +    cs->y  = -1;
 +}
 +
 +static void spatial_compose53i_dy_buffered(DWTCompose *cs, slice_buffer *sb,
 +                                           IDWTELEM *temp,
 +                                           int width, int height,
 +                                           int stride_line)
 +{
 +    int y = cs->y;
 +
 +    IDWTELEM *b0 = cs->b0;
 +    IDWTELEM *b1 = cs->b1;
 +    IDWTELEM *b2 = slice_buffer_get_line(sb,
 +                                         mirror(y + 1, height - 1) *
 +                                         stride_line);
 +    IDWTELEM *b3 = slice_buffer_get_line(sb,
 +                                         mirror(y + 2, height - 1) *
 +                                         stride_line);
 +
 +    if (y + 1 < (unsigned)height && y < (unsigned)height) {
 +        int x;
 +
 +        for (x = 0; x < width; x++) {
 +            b2[x] -= (b1[x] + b3[x] + 2) >> 2;
 +            b1[x] += (b0[x] + b2[x])     >> 1;
 +        }
 +    } else {
 +        if (y + 1 < (unsigned)height)
 +            vertical_compose53iL0(b1, b2, b3, width);
 +        if (y + 0 < (unsigned)height)
 +            vertical_compose53iH0(b0, b1, b2, width);
 +    }
 +
 +    if (y - 1 < (unsigned)height)
 +        horizontal_compose53i(b0, temp, width);
 +    if (y + 0 < (unsigned)height)
 +        horizontal_compose53i(b1, temp, width);
 +
 +    cs->b0  = b2;
 +    cs->b1  = b3;
 +    cs->y  += 2;
 +}
 +
 +static void spatial_compose53i_dy(DWTCompose *cs, IDWTELEM *buffer,
 +                                  IDWTELEM *temp, int width, int height,
 +                                  int stride)
 +{
 +    int y        = cs->y;
 +    IDWTELEM *b0 = cs->b0;
 +    IDWTELEM *b1 = cs->b1;
 +    IDWTELEM *b2 = buffer + mirror(y + 1, height - 1) * stride;
 +    IDWTELEM *b3 = buffer + mirror(y + 2, height - 1) * stride;
 +
 +    if (y + 1 < (unsigned)height)
 +        vertical_compose53iL0(b1, b2, b3, width);
 +    if (y + 0 < (unsigned)height)
 +        vertical_compose53iH0(b0, b1, b2, width);
 +
 +    if (y - 1 < (unsigned)height)
 +        horizontal_compose53i(b0, temp, width);
 +    if (y + 0 < (unsigned)height)
 +        horizontal_compose53i(b1, temp, width);
 +
 +    cs->b0  = b2;
 +    cs->b1  = b3;
 +    cs->y  += 2;
 +}
 +
 +void ff_snow_horizontal_compose97i(IDWTELEM *b, IDWTELEM *temp, int width)
 +{
 +    const int w2 = (width + 1) >> 1;
 +    int x;
 +
 +    temp[0] = b[0] - ((3 * b[w2] + 2) >> 2);
 +    for (x = 1; x < (width >> 1); x++) {
 +        temp[2 * x]     = b[x] - ((3 * (b[x + w2 - 1] + b[x + w2]) + 4) >> 3);
 +        temp[2 * x - 1] = b[x + w2 - 1] - temp[2 * x - 2] - temp[2 * x];
 +    }
 +    if (width & 1) {
 +        temp[2 * x]     = b[x] - ((3 * b[x + w2 - 1] + 2) >> 2);
 +        temp[2 * x - 1] = b[x + w2 - 1] - temp[2 * x - 2] - temp[2 * x];
 +    } else
 +        temp[2 * x - 1] = b[x + w2 - 1] - 2 * temp[2 * x - 2];
 +
 +    b[0] = temp[0] + ((2 * temp[0] + temp[1] + 4) >> 3);
 +    for (x = 2; x < width - 1; x += 2) {
 +        b[x]     = temp[x] + ((4 * temp[x] + temp[x - 1] + temp[x + 1] + 8) >> 4);
 +        b[x - 1] = temp[x - 1] + ((3 * (b[x - 2] + b[x])) >> 1);
 +    }
 +    if (width & 1) {
 +        b[x]     = temp[x] + ((2 * temp[x] + temp[x - 1] + 4) >> 3);
 +        b[x - 1] = temp[x - 1] + ((3 * (b[x - 2] + b[x])) >> 1);
 +    } else
 +        b[x - 1] = temp[x - 1] + 3 * b[x - 2];
 +}
 +
 +static void vertical_compose97iH0(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2,
 +                                  int width)
 +{
 +    int i;
 +
 +    for (i = 0; i < width; i++)
 +        b1[i] += (W_AM * (b0[i] + b2[i]) + W_AO) >> W_AS;
 +}
 +
 +static void vertical_compose97iH1(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2,
 +                                  int width)
 +{
 +    int i;
 +
 +    for (i = 0; i < width; i++)
 +        b1[i] -= (W_CM * (b0[i] + b2[i]) + W_CO) >> W_CS;
 +}
 +
 +static void vertical_compose97iL0(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2,
 +                                  int width)
 +{
 +    int i;
 +
 +    for (i = 0; i < width; i++)
 +        b1[i] += (W_BM * (b0[i] + b2[i]) + 4 * b1[i] + W_BO) >> W_BS;
 +}
 +
 +static void vertical_compose97iL1(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2,
 +                                  int width)
 +{
 +    int i;
 +
 +    for (i = 0; i < width; i++)
 +        b1[i] -= (W_DM * (b0[i] + b2[i]) + W_DO) >> W_DS;
 +}
 +
 +void ff_snow_vertical_compose97i(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2,
 +                                 IDWTELEM *b3, IDWTELEM *b4, IDWTELEM *b5,
 +                                 int width)
 +{
 +    int i;
 +
 +    for (i = 0; i < width; i++) {
 +        b4[i] -= (W_DM * (b3[i] + b5[i]) + W_DO) >> W_DS;
 +        b3[i] -= (W_CM * (b2[i] + b4[i]) + W_CO) >> W_CS;
 +        b2[i] += (W_BM * (b1[i] + b3[i]) + 4 * b2[i] + W_BO) >> W_BS;
 +        b1[i] += (W_AM * (b0[i] + b2[i]) + W_AO) >> W_AS;
 +    }
 +}
 +
 +static void spatial_compose97i_buffered_init(DWTCompose *cs, slice_buffer *sb,
 +                                             int height, int stride_line)
 +{
 +    cs->b0 = slice_buffer_get_line(sb, mirror(-3 - 1, height - 1) * stride_line);
 +    cs->b1 = slice_buffer_get_line(sb, mirror(-3,     height - 1) * stride_line);
 +    cs->b2 = slice_buffer_get_line(sb, mirror(-3 + 1, height - 1) * stride_line);
 +    cs->b3 = slice_buffer_get_line(sb, mirror(-3 + 2, height - 1) * stride_line);
 +    cs->y  = -3;
 +}
 +
 +static void spatial_compose97i_init(DWTCompose *cs, IDWTELEM *buffer, int height,
 +                                    int stride)
 +{
 +    cs->b0 = buffer + mirror(-3 - 1, height - 1) * stride;
 +    cs->b1 = buffer + mirror(-3,     height - 1) * stride;
 +    cs->b2 = buffer + mirror(-3 + 1, height - 1) * stride;
 +    cs->b3 = buffer + mirror(-3 + 2, height - 1) * stride;
 +    cs->y  = -3;
 +}
 +
 +static void spatial_compose97i_dy_buffered(SnowDWTContext *dsp, DWTCompose *cs,
 +                                           slice_buffer * sb, IDWTELEM *temp,
 +                                           int width, int height,
 +                                           int stride_line)
 +{
 +    int y = cs->y;
 +
 +    IDWTELEM *b0 = cs->b0;
 +    IDWTELEM *b1 = cs->b1;
 +    IDWTELEM *b2 = cs->b2;
 +    IDWTELEM *b3 = cs->b3;
 +    IDWTELEM *b4 = slice_buffer_get_line(sb,
 +                                         mirror(y + 3, height - 1) *
 +                                         stride_line);
 +    IDWTELEM *b5 = slice_buffer_get_line(sb,
 +                                         mirror(y + 4, height - 1) *
 +                                         stride_line);
 +
 +    if (y > 0 && y + 4 < height) {
 +        dsp->vertical_compose97i(b0, b1, b2, b3, b4, b5, width);
 +    } else {
 +        if (y + 3 < (unsigned)height)
 +            vertical_compose97iL1(b3, b4, b5, width);
 +        if (y + 2 < (unsigned)height)
 +            vertical_compose97iH1(b2, b3, b4, width);
 +        if (y + 1 < (unsigned)height)
 +            vertical_compose97iL0(b1, b2, b3, width);
 +        if (y + 0 < (unsigned)height)
 +            vertical_compose97iH0(b0, b1, b2, width);
 +    }
 +
 +    if (y - 1 < (unsigned)height)
 +        dsp->horizontal_compose97i(b0, temp, width);
 +    if (y + 0 < (unsigned)height)
 +        dsp->horizontal_compose97i(b1, temp, width);
 +
 +    cs->b0  = b2;
 +    cs->b1  = b3;
 +    cs->b2  = b4;
 +    cs->b3  = b5;
 +    cs->y  += 2;
 +}
 +
 +static void spatial_compose97i_dy(DWTCompose *cs, IDWTELEM *buffer,
 +                                  IDWTELEM *temp, int width, int height,
 +                                  int stride)
 +{
 +    int y        = cs->y;
 +    IDWTELEM *b0 = cs->b0;
 +    IDWTELEM *b1 = cs->b1;
 +    IDWTELEM *b2 = cs->b2;
 +    IDWTELEM *b3 = cs->b3;
 +    IDWTELEM *b4 = buffer + mirror(y + 3, height - 1) * stride;
 +    IDWTELEM *b5 = buffer + mirror(y + 4, height - 1) * stride;
 +
 +    if (y + 3 < (unsigned)height)
 +        vertical_compose97iL1(b3, b4, b5, width);
 +    if (y + 2 < (unsigned)height)
 +        vertical_compose97iH1(b2, b3, b4, width);
 +    if (y + 1 < (unsigned)height)
 +        vertical_compose97iL0(b1, b2, b3, width);
 +    if (y + 0 < (unsigned)height)
 +        vertical_compose97iH0(b0, b1, b2, width);
 +
 +    if (y - 1 < (unsigned)height)
 +        ff_snow_horizontal_compose97i(b0, temp, width);
 +    if (y + 0 < (unsigned)height)
 +        ff_snow_horizontal_compose97i(b1, temp, width);
 +
 +    cs->b0  = b2;
 +    cs->b1  = b3;
 +    cs->b2  = b4;
 +    cs->b3  = b5;
 +    cs->y  += 2;
 +}
 +
 +void ff_spatial_idwt_buffered_init(DWTCompose *cs, slice_buffer *sb, int width,
 +                                   int height, int stride_line, int type,
 +                                   int decomposition_count)
 +{
 +    int level;
 +    for (level = decomposition_count - 1; level >= 0; level--) {
 +        switch (type) {
 +        case DWT_97:
 +            spatial_compose97i_buffered_init(cs + level, sb, height >> level,
 +                                             stride_line << level);
 +            break;
 +        case DWT_53:
 +            spatial_compose53i_buffered_init(cs + level, sb, height >> level,
 +                                             stride_line << level);
 +            break;
 +        }
 +    }
 +}
 +
 +void ff_spatial_idwt_buffered_slice(SnowDWTContext *dsp, DWTCompose *cs,
 +                                    slice_buffer *slice_buf, IDWTELEM *temp,
 +                                    int width, int height, int stride_line,
 +                                    int type, int decomposition_count, int y)
 +{
 +    const int support = type == 1 ? 3 : 5;
 +    int level;
 +    if (type == 2)
 +        return;
 +
 +    for (level = decomposition_count - 1; level >= 0; level--)
 +        while (cs[level].y <= FFMIN((y >> level) + support, height >> level)) {
 +            switch (type) {
 +            case DWT_97:
 +                spatial_compose97i_dy_buffered(dsp, cs + level, slice_buf, temp,
 +                                               width >> level,
 +                                               height >> level,
 +                                               stride_line << level);
 +                break;
 +            case DWT_53:
 +                spatial_compose53i_dy_buffered(cs + level, slice_buf, temp,
 +                                               width >> level,
 +                                               height >> level,
 +                                               stride_line << level);
 +                break;
 +            }
 +        }
 +}
 +
 +static void ff_spatial_idwt_init(DWTCompose *cs, IDWTELEM *buffer, int width,
 +                                 int height, int stride, int type,
 +                                 int decomposition_count)
 +{
 +    int level;
 +    for (level = decomposition_count - 1; level >= 0; level--) {
 +        switch (type) {
 +        case DWT_97:
 +            spatial_compose97i_init(cs + level, buffer, height >> level,
 +                                    stride << level);
 +            break;
 +        case DWT_53:
 +            spatial_compose53i_init(cs + level, buffer, height >> level,
 +                                    stride << level);
 +            break;
 +        }
 +    }
 +}
 +
 +static void ff_spatial_idwt_slice(DWTCompose *cs, IDWTELEM *buffer,
 +                                  IDWTELEM *temp, int width, int height,
 +                                  int stride, int type,
 +                                  int decomposition_count, int y)
 +{
 +    const int support = type == 1 ? 3 : 5;
 +    int level;
 +    if (type == 2)
 +        return;
 +
 +    for (level = decomposition_count - 1; level >= 0; level--)
 +        while (cs[level].y <= FFMIN((y >> level) + support, height >> level)) {
 +            switch (type) {
 +            case DWT_97:
 +                spatial_compose97i_dy(cs + level, buffer, temp, width >> level,
 +                                      height >> level, stride << level);
 +                break;
 +            case DWT_53:
 +                spatial_compose53i_dy(cs + level, buffer, temp, width >> level,
 +                                      height >> level, stride << level);
 +                break;
 +            }
 +        }
 +}
 +
 +void ff_spatial_idwt(IDWTELEM *buffer, IDWTELEM *temp, int width, int height,
 +                     int stride, int type, int decomposition_count)
 +{
 +    DWTCompose cs[MAX_DECOMPOSITIONS];
 +    int y;
 +    ff_spatial_idwt_init(cs, buffer, width, height, stride, type,
 +                         decomposition_count);
 +    for (y = 0; y < height; y += 4)
 +        ff_spatial_idwt_slice(cs, buffer, temp, width, height, stride, type,
 +                              decomposition_count, y);
 +}
 +
 +static inline int w_c(struct MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, int line_size,
 +                      int w, int h, int type)
 +{
 +    int s, i, j;
 +    const int dec_count = w == 8 ? 3 : 4;
 +    int tmp[32 * 32], tmp2[32];
 +    int level, ori;
 +    static const int scale[2][2][4][4] = {
 +        {
 +            { // 9/7 8x8 dec=3
 +                { 268, 239, 239, 213 },
 +                { 0,   224, 224, 152 },
 +                { 0,   135, 135, 110 },
 +            },
 +            { // 9/7 16x16 or 32x32 dec=4
 +                { 344, 310, 310, 280 },
 +                { 0,   320, 320, 228 },
 +                { 0,   175, 175, 136 },
 +                { 0,   129, 129, 102 },
 +            }
 +        },
 +        {
 +            { // 5/3 8x8 dec=3
 +                { 275, 245, 245, 218 },
 +                { 0,   230, 230, 156 },
 +                { 0,   138, 138, 113 },
 +            },
 +            { // 5/3 16x16 or 32x32 dec=4
 +                { 352, 317, 317, 286 },
 +                { 0,   328, 328, 233 },
 +                { 0,   180, 180, 140 },
 +                { 0,   132, 132, 105 },
 +            }
 +        }
 +    };
 +
 +    for (i = 0; i < h; i++) {
 +        for (j = 0; j < w; j += 4) {
 +            tmp[32 * i + j + 0] = (pix1[j + 0] - pix2[j + 0]) << 4;
 +            tmp[32 * i + j + 1] = (pix1[j + 1] - pix2[j + 1]) << 4;
 +            tmp[32 * i + j + 2] = (pix1[j + 2] - pix2[j + 2]) << 4;
 +            tmp[32 * i + j + 3] = (pix1[j + 3] - pix2[j + 3]) << 4;
 +        }
 +        pix1 += line_size;
 +        pix2 += line_size;
 +    }
 +
 +    ff_spatial_dwt(tmp, tmp2, w, h, 32, type, dec_count);
 +
 +    s = 0;
 +    av_assert1(w == h);
 +    for (level = 0; level < dec_count; level++)
 +        for (ori = level ? 1 : 0; ori < 4; ori++) {
 +            int size   = w >> (dec_count - level);
 +            int sx     = (ori & 1) ? size : 0;
 +            int stride = 32 << (dec_count - level);
 +            int sy     = (ori & 2) ? stride >> 1 : 0;
 +
 +            for (i = 0; i < size; i++)
 +                for (j = 0; j < size; j++) {
 +                    int v = tmp[sx + sy + i * stride + j] *
 +                            scale[type][dec_count - 3][level][ori];
 +                    s += FFABS(v);
 +                }
 +        }
 +    av_assert1(s >= 0);
 +    return s >> 9;
 +}
 +
 +static int w53_8_c(struct MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h)
 +{
 +    return w_c(v, pix1, pix2, line_size, 8, h, 1);
 +}
 +
 +static int w97_8_c(struct MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h)
 +{
 +    return w_c(v, pix1, pix2, line_size, 8, h, 0);
 +}
 +
 +static int w53_16_c(struct MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h)
 +{
 +    return w_c(v, pix1, pix2, line_size, 16, h, 1);
 +}
 +
 +static int w97_16_c(struct MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h)
 +{
 +    return w_c(v, pix1, pix2, line_size, 16, h, 0);
 +}
 +
 +int ff_w53_32_c(struct MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h)
 +{
 +    return w_c(v, pix1, pix2, line_size, 32, h, 1);
 +}
 +
 +int ff_w97_32_c(struct MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h)
 +{
 +    return w_c(v, pix1, pix2, line_size, 32, h, 0);
 +}
 +
++void ff_dsputil_init_dwt(MECmpContext *c)
 +{
 +    c->w53[0] = w53_16_c;
 +    c->w53[1] = w53_8_c;
 +    c->w97[0] = w97_16_c;
 +    c->w97[1] = w97_8_c;
 +}
 +
 +void ff_dwt_init(SnowDWTContext *c)
 +{
 +    c->vertical_compose97i   = ff_snow_vertical_compose97i;
 +    c->horizontal_compose97i = ff_snow_horizontal_compose97i;
 +    c->inner_add_yblock      = ff_snow_inner_add_yblock;
 +
 +    if (HAVE_MMX)
 +        ff_dwt_init_x86(c);
 +}
 +
 +
index 7287a2e,0000000..327157b
mode 100644,000000..100644
--- /dev/null
@@@ -1,607 -1,0 +1,606 @@@
- #include "dsputil.h"
 +/*
 + * Copyright (C) 2004 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
 + */
 +
 +#include "libavutil/intmath.h"
 +#include "libavutil/log.h"
 +#include "libavutil/opt.h"
 +#include "avcodec.h"
 +#include "snow_dwt.h"
 +#include "internal.h"
 +#include "snow.h"
 +
 +#include "rangecoder.h"
 +#include "mathops.h"
 +
 +#include "mpegvideo.h"
 +#include "h263.h"
 +
 +static av_always_inline void predict_slice_buffered(SnowContext *s, slice_buffer * sb, IDWTELEM * old_buffer, int plane_index, int add, int mb_y){
 +    Plane *p= &s->plane[plane_index];
 +    const int mb_w= s->b_width  << s->block_max_depth;
 +    const int mb_h= s->b_height << s->block_max_depth;
 +    int x, y, mb_x;
 +    int block_size = MB_SIZE >> s->block_max_depth;
 +    int block_w    = plane_index ? block_size>>s->chroma_h_shift : block_size;
 +    int block_h    = plane_index ? block_size>>s->chroma_v_shift : block_size;
 +    const uint8_t *obmc  = plane_index ? ff_obmc_tab[s->block_max_depth+s->chroma_h_shift] : ff_obmc_tab[s->block_max_depth];
 +    int obmc_stride= plane_index ? (2*block_size)>>s->chroma_h_shift : 2*block_size;
 +    int ref_stride= s->current_picture->linesize[plane_index];
 +    uint8_t *dst8= s->current_picture->data[plane_index];
 +    int w= p->width;
 +    int h= p->height;
 +
 +    if(s->keyframe || (s->avctx->debug&512)){
 +        if(mb_y==mb_h)
 +            return;
 +
 +        if(add){
 +            for(y=block_h*mb_y; y<FFMIN(h,block_h*(mb_y+1)); y++){
 +//                DWTELEM * line = slice_buffer_get_line(sb, y);
 +                IDWTELEM * line = sb->line[y];
 +                for(x=0; x<w; x++){
 +//                    int v= buf[x + y*w] + (128<<FRAC_BITS) + (1<<(FRAC_BITS-1));
 +                    int v= line[x] + (128<<FRAC_BITS) + (1<<(FRAC_BITS-1));
 +                    v >>= FRAC_BITS;
 +                    if(v&(~255)) v= ~(v>>31);
 +                    dst8[x + y*ref_stride]= v;
 +                }
 +            }
 +        }else{
 +            for(y=block_h*mb_y; y<FFMIN(h,block_h*(mb_y+1)); y++){
 +//                DWTELEM * line = slice_buffer_get_line(sb, y);
 +                IDWTELEM * line = sb->line[y];
 +                for(x=0; x<w; x++){
 +                    line[x] -= 128 << FRAC_BITS;
 +//                    buf[x + y*w]-= 128<<FRAC_BITS;
 +                }
 +            }
 +        }
 +
 +        return;
 +    }
 +
 +    for(mb_x=0; mb_x<=mb_w; mb_x++){
 +        add_yblock(s, 1, sb, old_buffer, dst8, obmc,
 +                   block_w*mb_x - block_w/2,
 +                   block_h*mb_y - block_h/2,
 +                   block_w, block_h,
 +                   w, h,
 +                   w, ref_stride, obmc_stride,
 +                   mb_x - 1, mb_y - 1,
 +                   add, 0, plane_index);
 +    }
 +}
 +
 +static inline void decode_subband_slice_buffered(SnowContext *s, SubBand *b, slice_buffer * sb, int start_y, int h, int save_state[1]){
 +    const int w= b->width;
 +    int y;
 +    const int qlog= av_clip(s->qlog + b->qlog, 0, QROOT*16);
 +    int qmul= ff_qexp[qlog&(QROOT-1)]<<(qlog>>QSHIFT);
 +    int qadd= (s->qbias*qmul)>>QBIAS_SHIFT;
 +    int new_index = 0;
 +
 +    if(b->ibuf == s->spatial_idwt_buffer || s->qlog == LOSSLESS_QLOG){
 +        qadd= 0;
 +        qmul= 1<<QEXPSHIFT;
 +    }
 +
 +    /* If we are on the second or later slice, restore our index. */
 +    if (start_y != 0)
 +        new_index = save_state[0];
 +
 +
 +    for(y=start_y; y<h; y++){
 +        int x = 0;
 +        int v;
 +        IDWTELEM * line = slice_buffer_get_line(sb, y * b->stride_line + b->buf_y_offset) + b->buf_x_offset;
 +        memset(line, 0, b->width*sizeof(IDWTELEM));
 +        v = b->x_coeff[new_index].coeff;
 +        x = b->x_coeff[new_index++].x;
 +        while(x < w){
 +            register int t= ( (v>>1)*qmul + qadd)>>QEXPSHIFT;
 +            register int u= -(v&1);
 +            line[x] = (t^u) - u;
 +
 +            v = b->x_coeff[new_index].coeff;
 +            x = b->x_coeff[new_index++].x;
 +        }
 +    }
 +
 +    /* Save our variables for the next slice. */
 +    save_state[0] = new_index;
 +
 +    return;
 +}
 +
 +static int decode_q_branch(SnowContext *s, int level, int x, int y){
 +    const int w= s->b_width << s->block_max_depth;
 +    const int rem_depth= s->block_max_depth - level;
 +    const int index= (x + y*w) << rem_depth;
 +    int trx= (x+1)<<rem_depth;
 +    const BlockNode *left  = x ? &s->block[index-1] : &null_block;
 +    const BlockNode *top   = y ? &s->block[index-w] : &null_block;
 +    const BlockNode *tl    = y && x ? &s->block[index-w-1] : left;
 +    const BlockNode *tr    = y && trx<w && ((x&1)==0 || level==0) ? &s->block[index-w+(1<<rem_depth)] : tl; //FIXME use lt
 +    int s_context= 2*left->level + 2*top->level + tl->level + tr->level;
 +    int res;
 +
 +    if(s->keyframe){
 +        set_blocks(s, level, x, y, null_block.color[0], null_block.color[1], null_block.color[2], null_block.mx, null_block.my, null_block.ref, BLOCK_INTRA);
 +        return 0;
 +    }
 +
 +    if(level==s->block_max_depth || get_rac(&s->c, &s->block_state[4 + s_context])){
 +        int type, mx, my;
 +        int l = left->color[0];
 +        int cb= left->color[1];
 +        int cr= left->color[2];
 +        int ref = 0;
 +        int ref_context= av_log2(2*left->ref) + av_log2(2*top->ref);
 +        int mx_context= av_log2(2*FFABS(left->mx - top->mx)) + 0*av_log2(2*FFABS(tr->mx - top->mx));
 +        int my_context= av_log2(2*FFABS(left->my - top->my)) + 0*av_log2(2*FFABS(tr->my - top->my));
 +
 +        type= get_rac(&s->c, &s->block_state[1 + left->type + top->type]) ? BLOCK_INTRA : 0;
 +
 +        if(type){
 +            pred_mv(s, &mx, &my, 0, left, top, tr);
 +            l += get_symbol(&s->c, &s->block_state[32], 1);
 +            if (s->nb_planes > 2) {
 +                cb+= get_symbol(&s->c, &s->block_state[64], 1);
 +                cr+= get_symbol(&s->c, &s->block_state[96], 1);
 +            }
 +        }else{
 +            if(s->ref_frames > 1)
 +                ref= get_symbol(&s->c, &s->block_state[128 + 1024 + 32*ref_context], 0);
 +            if (ref >= s->ref_frames) {
 +                av_log(s->avctx, AV_LOG_ERROR, "Invalid ref\n");
 +                return AVERROR_INVALIDDATA;
 +            }
 +            pred_mv(s, &mx, &my, ref, left, top, tr);
 +            mx+= get_symbol(&s->c, &s->block_state[128 + 32*(mx_context + 16*!!ref)], 1);
 +            my+= get_symbol(&s->c, &s->block_state[128 + 32*(my_context + 16*!!ref)], 1);
 +        }
 +        set_blocks(s, level, x, y, l, cb, cr, mx, my, ref, type);
 +    }else{
 +        if ((res = decode_q_branch(s, level+1, 2*x+0, 2*y+0)) < 0 ||
 +            (res = decode_q_branch(s, level+1, 2*x+1, 2*y+0)) < 0 ||
 +            (res = decode_q_branch(s, level+1, 2*x+0, 2*y+1)) < 0 ||
 +            (res = decode_q_branch(s, level+1, 2*x+1, 2*y+1)) < 0)
 +            return res;
 +    }
 +    return 0;
 +}
 +
 +static void dequantize_slice_buffered(SnowContext *s, slice_buffer * sb, SubBand *b, IDWTELEM *src, int stride, int start_y, int end_y){
 +    const int w= b->width;
 +    const int qlog= av_clip(s->qlog + b->qlog, 0, QROOT*16);
 +    const int qmul= ff_qexp[qlog&(QROOT-1)]<<(qlog>>QSHIFT);
 +    const int qadd= (s->qbias*qmul)>>QBIAS_SHIFT;
 +    int x,y;
 +
 +    if(s->qlog == LOSSLESS_QLOG) return;
 +
 +    for(y=start_y; y<end_y; y++){
 +//        DWTELEM * line = slice_buffer_get_line_from_address(sb, src + (y * stride));
 +        IDWTELEM * line = slice_buffer_get_line(sb, (y * b->stride_line) + b->buf_y_offset) + b->buf_x_offset;
 +        for(x=0; x<w; x++){
 +            int i= line[x];
 +            if(i<0){
 +                line[x]= -((-i*qmul + qadd)>>(QEXPSHIFT)); //FIXME try different bias
 +            }else if(i>0){
 +                line[x]=  (( i*qmul + qadd)>>(QEXPSHIFT));
 +            }
 +        }
 +    }
 +}
 +
 +static void correlate_slice_buffered(SnowContext *s, slice_buffer * sb, SubBand *b, IDWTELEM *src, int stride, int inverse, int use_median, int start_y, int end_y){
 +    const int w= b->width;
 +    int x,y;
 +
 +    IDWTELEM * line=0; // silence silly "could be used without having been initialized" warning
 +    IDWTELEM * prev;
 +
 +    if (start_y != 0)
 +        line = slice_buffer_get_line(sb, ((start_y - 1) * b->stride_line) + b->buf_y_offset) + b->buf_x_offset;
 +
 +    for(y=start_y; y<end_y; y++){
 +        prev = line;
 +//        line = slice_buffer_get_line_from_address(sb, src + (y * stride));
 +        line = slice_buffer_get_line(sb, (y * b->stride_line) + b->buf_y_offset) + b->buf_x_offset;
 +        for(x=0; x<w; x++){
 +            if(x){
 +                if(use_median){
 +                    if(y && x+1<w) line[x] += mid_pred(line[x - 1], prev[x], prev[x + 1]);
 +                    else  line[x] += line[x - 1];
 +                }else{
 +                    if(y) line[x] += mid_pred(line[x - 1], prev[x], line[x - 1] + prev[x] - prev[x - 1]);
 +                    else  line[x] += line[x - 1];
 +                }
 +            }else{
 +                if(y) line[x] += prev[x];
 +            }
 +        }
 +    }
 +}
 +
 +static void decode_qlogs(SnowContext *s){
 +    int plane_index, level, orientation;
 +
 +    for(plane_index=0; plane_index < s->nb_planes; plane_index++){
 +        for(level=0; level<s->spatial_decomposition_count; level++){
 +            for(orientation=level ? 1:0; orientation<4; orientation++){
 +                int q;
 +                if     (plane_index==2) q= s->plane[1].band[level][orientation].qlog;
 +                else if(orientation==2) q= s->plane[plane_index].band[level][1].qlog;
 +                else                    q= get_symbol(&s->c, s->header_state, 1);
 +                s->plane[plane_index].band[level][orientation].qlog= q;
 +            }
 +        }
 +    }
 +}
 +
 +#define GET_S(dst, check) \
 +    tmp= get_symbol(&s->c, s->header_state, 0);\
 +    if(!(check)){\
 +        av_log(s->avctx, AV_LOG_ERROR, "Error " #dst " is %d\n", tmp);\
 +        return AVERROR_INVALIDDATA;\
 +    }\
 +    dst= tmp;
 +
 +static int decode_header(SnowContext *s){
 +    int plane_index, tmp;
 +    uint8_t kstate[32];
 +
 +    memset(kstate, MID_STATE, sizeof(kstate));
 +
 +    s->keyframe= get_rac(&s->c, kstate);
 +    if(s->keyframe || s->always_reset){
 +        ff_snow_reset_contexts(s);
 +        s->spatial_decomposition_type=
 +        s->qlog=
 +        s->qbias=
 +        s->mv_scale=
 +        s->block_max_depth= 0;
 +    }
 +    if(s->keyframe){
 +        GET_S(s->version, tmp <= 0U)
 +        s->always_reset= get_rac(&s->c, s->header_state);
 +        s->temporal_decomposition_type= get_symbol(&s->c, s->header_state, 0);
 +        s->temporal_decomposition_count= get_symbol(&s->c, s->header_state, 0);
 +        GET_S(s->spatial_decomposition_count, 0 < tmp && tmp <= MAX_DECOMPOSITIONS)
 +        s->colorspace_type= get_symbol(&s->c, s->header_state, 0);
 +        if (s->colorspace_type == 1) {
 +            s->avctx->pix_fmt= AV_PIX_FMT_GRAY8;
 +            s->nb_planes = 1;
 +        } else if(s->colorspace_type == 0) {
 +            s->chroma_h_shift= get_symbol(&s->c, s->header_state, 0);
 +            s->chroma_v_shift= get_symbol(&s->c, s->header_state, 0);
 +
 +            if(s->chroma_h_shift == 1 && s->chroma_v_shift==1){
 +                s->avctx->pix_fmt= AV_PIX_FMT_YUV420P;
 +            }else if(s->chroma_h_shift == 0 && s->chroma_v_shift==0){
 +                s->avctx->pix_fmt= AV_PIX_FMT_YUV444P;
 +            }else if(s->chroma_h_shift == 2 && s->chroma_v_shift==2){
 +                s->avctx->pix_fmt= AV_PIX_FMT_YUV410P;
 +            } else {
 +                av_log(s, AV_LOG_ERROR, "unsupported color subsample mode %d %d\n", s->chroma_h_shift, s->chroma_v_shift);
 +                s->chroma_h_shift = s->chroma_v_shift = 1;
 +                s->avctx->pix_fmt= AV_PIX_FMT_YUV420P;
 +                return AVERROR_INVALIDDATA;
 +            }
 +            s->nb_planes = 3;
 +        } else {
 +            av_log(s, AV_LOG_ERROR, "unsupported color space\n");
 +            s->chroma_h_shift = s->chroma_v_shift = 1;
 +            s->avctx->pix_fmt= AV_PIX_FMT_YUV420P;
 +            return AVERROR_INVALIDDATA;
 +        }
 +
 +
 +        s->spatial_scalability= get_rac(&s->c, s->header_state);
 +//        s->rate_scalability= get_rac(&s->c, s->header_state);
 +        GET_S(s->max_ref_frames, tmp < (unsigned)MAX_REF_FRAMES)
 +        s->max_ref_frames++;
 +
 +        decode_qlogs(s);
 +    }
 +
 +    if(!s->keyframe){
 +        if(get_rac(&s->c, s->header_state)){
 +            for(plane_index=0; plane_index<FFMIN(s->nb_planes, 2); plane_index++){
 +                int htaps, i, sum=0;
 +                Plane *p= &s->plane[plane_index];
 +                p->diag_mc= get_rac(&s->c, s->header_state);
 +                htaps= get_symbol(&s->c, s->header_state, 0)*2 + 2;
 +                if((unsigned)htaps > HTAPS_MAX || htaps==0)
 +                    return AVERROR_INVALIDDATA;
 +                p->htaps= htaps;
 +                for(i= htaps/2; i; i--){
 +                    p->hcoeff[i]= get_symbol(&s->c, s->header_state, 0) * (1-2*(i&1));
 +                    sum += p->hcoeff[i];
 +                }
 +                p->hcoeff[0]= 32-sum;
 +            }
 +            s->plane[2].diag_mc= s->plane[1].diag_mc;
 +            s->plane[2].htaps  = s->plane[1].htaps;
 +            memcpy(s->plane[2].hcoeff, s->plane[1].hcoeff, sizeof(s->plane[1].hcoeff));
 +        }
 +        if(get_rac(&s->c, s->header_state)){
 +            GET_S(s->spatial_decomposition_count, 0 < tmp && tmp <= MAX_DECOMPOSITIONS)
 +            decode_qlogs(s);
 +        }
 +    }
 +
 +    s->spatial_decomposition_type+= get_symbol(&s->c, s->header_state, 1);
 +    if(s->spatial_decomposition_type > 1U){
 +        av_log(s->avctx, AV_LOG_ERROR, "spatial_decomposition_type %d not supported\n", s->spatial_decomposition_type);
 +        return AVERROR_INVALIDDATA;
 +    }
 +    if(FFMIN(s->avctx-> width>>s->chroma_h_shift,
 +             s->avctx->height>>s->chroma_v_shift) >> (s->spatial_decomposition_count-1) <= 1){
 +        av_log(s->avctx, AV_LOG_ERROR, "spatial_decomposition_count %d too large for size\n", s->spatial_decomposition_count);
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +
 +    s->qlog           += get_symbol(&s->c, s->header_state, 1);
 +    s->mv_scale       += get_symbol(&s->c, s->header_state, 1);
 +    s->qbias          += get_symbol(&s->c, s->header_state, 1);
 +    s->block_max_depth+= get_symbol(&s->c, s->header_state, 1);
 +    if(s->block_max_depth > 1 || s->block_max_depth < 0){
 +        av_log(s->avctx, AV_LOG_ERROR, "block_max_depth= %d is too large\n", s->block_max_depth);
 +        s->block_max_depth= 0;
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    return 0;
 +}
 +
 +static av_cold int decode_init(AVCodecContext *avctx)
 +{
 +    int ret;
 +
 +    if ((ret = ff_snow_common_init(avctx)) < 0) {
 +        ff_snow_common_end(avctx->priv_data);
 +        return ret;
 +    }
 +
 +    return 0;
 +}
 +
 +static int decode_blocks(SnowContext *s){
 +    int x, y;
 +    int w= s->b_width;
 +    int h= s->b_height;
 +    int res;
 +
 +    for(y=0; y<h; y++){
 +        for(x=0; x<w; x++){
 +            if ((res = decode_q_branch(s, 0, x, y)) < 0)
 +                return res;
 +        }
 +    }
 +    return 0;
 +}
 +
 +static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
 +                        AVPacket *avpkt)
 +{
 +    const uint8_t *buf = avpkt->data;
 +    int buf_size = avpkt->size;
 +    SnowContext *s = avctx->priv_data;
 +    RangeCoder * const c= &s->c;
 +    int bytes_read;
 +    AVFrame *picture = data;
 +    int level, orientation, plane_index;
 +    int res;
 +
 +    ff_init_range_decoder(c, buf, buf_size);
 +    ff_build_rac_states(c, 0.05*(1LL<<32), 256-8);
 +
 +    s->current_picture->pict_type= AV_PICTURE_TYPE_I; //FIXME I vs. P
 +    if ((res = decode_header(s)) < 0)
 +        return res;
 +    if ((res=ff_snow_common_init_after_header(avctx)) < 0)
 +        return res;
 +
 +    // realloc slice buffer for the case that spatial_decomposition_count changed
 +    ff_slice_buffer_destroy(&s->sb);
 +    if ((res = ff_slice_buffer_init(&s->sb, s->plane[0].height,
 +                                    (MB_SIZE >> s->block_max_depth) +
 +                                    s->spatial_decomposition_count * 11 + 1,
 +                                    s->plane[0].width,
 +                                    s->spatial_idwt_buffer)) < 0)
 +        return res;
 +
 +    for(plane_index=0; plane_index < s->nb_planes; plane_index++){
 +        Plane *p= &s->plane[plane_index];
 +        p->fast_mc= p->diag_mc && p->htaps==6 && p->hcoeff[0]==40
 +                                              && p->hcoeff[1]==-10
 +                                              && p->hcoeff[2]==2;
 +    }
 +
 +    ff_snow_alloc_blocks(s);
 +
 +    if((res = ff_snow_frame_start(s)) < 0)
 +        return res;
 +    //keyframe flag duplication mess FIXME
 +    if(avctx->debug&FF_DEBUG_PICT_INFO)
 +        av_log(avctx, AV_LOG_ERROR,
 +               "keyframe:%d qlog:%d qbias: %d mvscale: %d "
 +               "decomposition_type:%d decomposition_count:%d\n",
 +               s->keyframe, s->qlog, s->qbias, s->mv_scale,
 +               s->spatial_decomposition_type,
 +               s->spatial_decomposition_count
 +              );
 +
 +    if ((res = decode_blocks(s)) < 0)
 +        return res;
 +
 +    for(plane_index=0; plane_index < s->nb_planes; plane_index++){
 +        Plane *p= &s->plane[plane_index];
 +        int w= p->width;
 +        int h= p->height;
 +        int x, y;
 +        int decode_state[MAX_DECOMPOSITIONS][4][1]; /* Stored state info for unpack_coeffs. 1 variable per instance. */
 +
 +        if(s->avctx->debug&2048){
 +            memset(s->spatial_dwt_buffer, 0, sizeof(DWTELEM)*w*h);
 +            predict_plane(s, s->spatial_idwt_buffer, plane_index, 1);
 +
 +            for(y=0; y<h; y++){
 +                for(x=0; x<w; x++){
 +                    int v= s->current_picture->data[plane_index][y*s->current_picture->linesize[plane_index] + x];
 +                    s->mconly_picture->data[plane_index][y*s->mconly_picture->linesize[plane_index] + x]= v;
 +                }
 +            }
 +        }
 +
 +        {
 +        for(level=0; level<s->spatial_decomposition_count; level++){
 +            for(orientation=level ? 1 : 0; orientation<4; orientation++){
 +                SubBand *b= &p->band[level][orientation];
 +                unpack_coeffs(s, b, b->parent, orientation);
 +            }
 +        }
 +        }
 +
 +        {
 +        const int mb_h= s->b_height << s->block_max_depth;
 +        const int block_size = MB_SIZE >> s->block_max_depth;
 +        const int block_h    = plane_index ? block_size>>s->chroma_v_shift : block_size;
 +        int mb_y;
 +        DWTCompose cs[MAX_DECOMPOSITIONS];
 +        int yd=0, yq=0;
 +        int y;
 +        int end_y;
 +
 +        ff_spatial_idwt_buffered_init(cs, &s->sb, w, h, 1, s->spatial_decomposition_type, s->spatial_decomposition_count);
 +        for(mb_y=0; mb_y<=mb_h; mb_y++){
 +
 +            int slice_starty = block_h*mb_y;
 +            int slice_h = block_h*(mb_y+1);
 +
 +            if (!(s->keyframe || s->avctx->debug&512)){
 +                slice_starty = FFMAX(0, slice_starty - (block_h >> 1));
 +                slice_h -= (block_h >> 1);
 +            }
 +
 +            for(level=0; level<s->spatial_decomposition_count; level++){
 +                for(orientation=level ? 1 : 0; orientation<4; orientation++){
 +                    SubBand *b= &p->band[level][orientation];
 +                    int start_y;
 +                    int end_y;
 +                    int our_mb_start = mb_y;
 +                    int our_mb_end = (mb_y + 1);
 +                    const int extra= 3;
 +                    start_y = (mb_y ? ((block_h * our_mb_start) >> (s->spatial_decomposition_count - level)) + s->spatial_decomposition_count - level + extra: 0);
 +                    end_y = (((block_h * our_mb_end) >> (s->spatial_decomposition_count - level)) + s->spatial_decomposition_count - level + extra);
 +                    if (!(s->keyframe || s->avctx->debug&512)){
 +                        start_y = FFMAX(0, start_y - (block_h >> (1+s->spatial_decomposition_count - level)));
 +                        end_y = FFMAX(0, end_y - (block_h >> (1+s->spatial_decomposition_count - level)));
 +                    }
 +                    start_y = FFMIN(b->height, start_y);
 +                    end_y = FFMIN(b->height, end_y);
 +
 +                    if (start_y != end_y){
 +                        if (orientation == 0){
 +                            SubBand * correlate_band = &p->band[0][0];
 +                            int correlate_end_y = FFMIN(b->height, end_y + 1);
 +                            int correlate_start_y = FFMIN(b->height, (start_y ? start_y + 1 : 0));
 +                            decode_subband_slice_buffered(s, correlate_band, &s->sb, correlate_start_y, correlate_end_y, decode_state[0][0]);
 +                            correlate_slice_buffered(s, &s->sb, correlate_band, correlate_band->ibuf, correlate_band->stride, 1, 0, correlate_start_y, correlate_end_y);
 +                            dequantize_slice_buffered(s, &s->sb, correlate_band, correlate_band->ibuf, correlate_band->stride, start_y, end_y);
 +                        }
 +                        else
 +                            decode_subband_slice_buffered(s, b, &s->sb, start_y, end_y, decode_state[level][orientation]);
 +                    }
 +                }
 +            }
 +
 +            for(; yd<slice_h; yd+=4){
 +                ff_spatial_idwt_buffered_slice(&s->dwt, cs, &s->sb, s->temp_idwt_buffer, w, h, 1, s->spatial_decomposition_type, s->spatial_decomposition_count, yd);
 +            }
 +
 +            if(s->qlog == LOSSLESS_QLOG){
 +                for(; yq<slice_h && yq<h; yq++){
 +                    IDWTELEM * line = slice_buffer_get_line(&s->sb, yq);
 +                    for(x=0; x<w; x++){
 +                        line[x] <<= FRAC_BITS;
 +                    }
 +                }
 +            }
 +
 +            predict_slice_buffered(s, &s->sb, s->spatial_idwt_buffer, plane_index, 1, mb_y);
 +
 +            y = FFMIN(p->height, slice_starty);
 +            end_y = FFMIN(p->height, slice_h);
 +            while(y < end_y)
 +                ff_slice_buffer_release(&s->sb, y++);
 +        }
 +
 +        ff_slice_buffer_flush(&s->sb);
 +        }
 +
 +    }
 +
 +    emms_c();
 +
 +    ff_snow_release_buffer(avctx);
 +
 +    if(!(s->avctx->debug&2048))
 +        res = av_frame_ref(picture, s->current_picture);
 +    else
 +        res = av_frame_ref(picture, s->mconly_picture);
 +
 +    if (res < 0)
 +        return res;
 +
 +    *got_frame = 1;
 +
 +    bytes_read= c->bytestream - c->bytestream_start;
 +    if(bytes_read ==0) av_log(s->avctx, AV_LOG_ERROR, "error at end of frame\n"); //FIXME
 +
 +    return bytes_read;
 +}
 +
 +static av_cold int decode_end(AVCodecContext *avctx)
 +{
 +    SnowContext *s = avctx->priv_data;
 +
 +    ff_slice_buffer_destroy(&s->sb);
 +
 +    ff_snow_common_end(s);
 +
 +    return 0;
 +}
 +
 +AVCodec ff_snow_decoder = {
 +    .name           = "snow",
 +    .long_name      = NULL_IF_CONFIG_SMALL("Snow"),
 +    .type           = AVMEDIA_TYPE_VIDEO,
 +    .id             = AV_CODEC_ID_SNOW,
 +    .priv_data_size = sizeof(SnowContext),
 +    .init           = decode_init,
 +    .close          = decode_end,
 +    .decode         = decode_frame,
 +    .capabilities   = CODEC_CAP_DR1 /*| CODEC_CAP_DRAW_HORIZ_BAND*/,
 +};
index 0911392,0000000..0fae0a6
mode 100644,000000..100644
--- /dev/null
@@@ -1,2026 -1,0 +1,2025 @@@
- #include "dsputil.h"
 +/*
 + * Copyright (C) 2004 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
 + */
 +
 +#include "libavutil/intmath.h"
 +#include "libavutil/log.h"
 +#include "libavutil/opt.h"
 +#include "avcodec.h"
-     ff_set_cmp(&s->dsp, s->dsp.me_cmp, s->avctx->me_cmp);
-     ff_set_cmp(&s->dsp, s->dsp.me_sub_cmp, s->avctx->me_sub_cmp);
 +#include "internal.h"
 +#include "snow_dwt.h"
 +#include "snow.h"
 +
 +#include "rangecoder.h"
 +#include "mathops.h"
 +
 +#include "mpegvideo.h"
 +#include "h263.h"
 +
 +static av_cold int encode_init(AVCodecContext *avctx)
 +{
 +    SnowContext *s = avctx->priv_data;
 +    int plane_index, ret;
 +    int i;
 +
 +    if(avctx->prediction_method == DWT_97
 +       && (avctx->flags & CODEC_FLAG_QSCALE)
 +       && avctx->global_quality == 0){
 +        av_log(avctx, AV_LOG_ERROR, "The 9/7 wavelet is incompatible with lossless mode.\n");
 +        return -1;
 +    }
 +
 +    s->spatial_decomposition_type= avctx->prediction_method; //FIXME add decorrelator type r transform_type
 +
 +    s->mv_scale       = (avctx->flags & CODEC_FLAG_QPEL) ? 2 : 4;
 +    s->block_max_depth= (avctx->flags & CODEC_FLAG_4MV ) ? 1 : 0;
 +
 +    for(plane_index=0; plane_index<3; plane_index++){
 +        s->plane[plane_index].diag_mc= 1;
 +        s->plane[plane_index].htaps= 6;
 +        s->plane[plane_index].hcoeff[0]=  40;
 +        s->plane[plane_index].hcoeff[1]= -10;
 +        s->plane[plane_index].hcoeff[2]=   2;
 +        s->plane[plane_index].fast_mc= 1;
 +    }
 +
 +    if ((ret = ff_snow_common_init(avctx)) < 0) {
 +        ff_snow_common_end(avctx->priv_data);
 +        return ret;
 +    }
 +    ff_mpegvideoencdsp_init(&s->mpvencdsp, avctx);
 +
 +    ff_snow_alloc_blocks(s);
 +
 +    s->version=0;
 +
 +    s->m.avctx   = avctx;
 +    s->m.flags   = avctx->flags;
 +    s->m.bit_rate= avctx->bit_rate;
 +
 +    s->m.me.temp      =
 +    s->m.me.scratchpad= av_mallocz_array((avctx->width+64), 2*16*2*sizeof(uint8_t));
 +    s->m.me.map       = av_mallocz(ME_MAP_SIZE*sizeof(uint32_t));
 +    s->m.me.score_map = av_mallocz(ME_MAP_SIZE*sizeof(uint32_t));
 +    s->m.obmc_scratchpad= av_mallocz(MB_SIZE*MB_SIZE*12*sizeof(uint32_t));
 +    if (!s->m.me.scratchpad || !s->m.me.map || !s->m.me.score_map || !s->m.obmc_scratchpad)
 +        return AVERROR(ENOMEM);
 +
 +    ff_h263_encode_init(&s->m); //mv_penalty
 +
 +    s->max_ref_frames = FFMAX(FFMIN(avctx->refs, MAX_REF_FRAMES), 1);
 +
 +    if(avctx->flags&CODEC_FLAG_PASS1){
 +        if(!avctx->stats_out)
 +            avctx->stats_out = av_mallocz(256);
 +
 +        if (!avctx->stats_out)
 +            return AVERROR(ENOMEM);
 +    }
 +    if((avctx->flags&CODEC_FLAG_PASS2) || !(avctx->flags&CODEC_FLAG_QSCALE)){
 +        if(ff_rate_control_init(&s->m) < 0)
 +            return -1;
 +    }
 +    s->pass1_rc= !(avctx->flags & (CODEC_FLAG_QSCALE|CODEC_FLAG_PASS2));
 +
 +    switch(avctx->pix_fmt){
 +    case AV_PIX_FMT_YUV444P:
 +//    case AV_PIX_FMT_YUV422P:
 +    case AV_PIX_FMT_YUV420P:
 +//    case AV_PIX_FMT_YUV411P:
 +    case AV_PIX_FMT_YUV410P:
 +        s->nb_planes = 3;
 +        s->colorspace_type= 0;
 +        break;
 +    case AV_PIX_FMT_GRAY8:
 +        s->nb_planes = 1;
 +        s->colorspace_type = 1;
 +        break;
 +/*    case AV_PIX_FMT_RGB32:
 +        s->colorspace= 1;
 +        break;*/
 +    default:
 +        av_log(avctx, AV_LOG_ERROR, "pixel format not supported\n");
 +        return -1;
 +    }
 +    avcodec_get_chroma_sub_sample(avctx->pix_fmt, &s->chroma_h_shift, &s->chroma_v_shift);
 +
-                 distortion += s->dsp.me_cmp[0](&s->m, src + off, dst + off, ref_stride, 16);
++    ff_set_cmp(&s->mecc, s->mecc.me_cmp, s->avctx->me_cmp);
++    ff_set_cmp(&s->mecc, s->mecc.me_sub_cmp, s->avctx->me_sub_cmp);
 +
 +    s->input_picture = av_frame_alloc();
 +    if (!s->input_picture)
 +        return AVERROR(ENOMEM);
 +
 +    if ((ret = ff_snow_get_buffer(s, s->input_picture)) < 0)
 +        return ret;
 +
 +    if(s->avctx->me_method == ME_ITER){
 +        int size= s->b_width * s->b_height << 2*s->block_max_depth;
 +        for(i=0; i<s->max_ref_frames; i++){
 +            s->ref_mvs[i]= av_mallocz_array(size, sizeof(int16_t[2]));
 +            s->ref_scores[i]= av_mallocz_array(size, sizeof(uint32_t));
 +            if (!s->ref_mvs[i] || !s->ref_scores[i])
 +                return AVERROR(ENOMEM);
 +        }
 +    }
 +
 +    return 0;
 +}
 +
 +//near copy & paste from dsputil, FIXME
 +static int pix_sum(uint8_t * pix, int line_size, int w, int h)
 +{
 +    int s, i, j;
 +
 +    s = 0;
 +    for (i = 0; i < h; i++) {
 +        for (j = 0; j < w; j++) {
 +            s += pix[0];
 +            pix ++;
 +        }
 +        pix += line_size - w;
 +    }
 +    return s;
 +}
 +
 +//near copy & paste from dsputil, FIXME
 +static int pix_norm1(uint8_t * pix, int line_size, int w)
 +{
 +    int s, i, j;
 +    uint32_t *sq = ff_square_tab + 256;
 +
 +    s = 0;
 +    for (i = 0; i < w; i++) {
 +        for (j = 0; j < w; j ++) {
 +            s += sq[pix[0]];
 +            pix ++;
 +        }
 +        pix += line_size - w;
 +    }
 +    return s;
 +}
 +
 +static inline int get_penalty_factor(int lambda, int lambda2, int type){
 +    switch(type&0xFF){
 +    default:
 +    case FF_CMP_SAD:
 +        return lambda>>FF_LAMBDA_SHIFT;
 +    case FF_CMP_DCT:
 +        return (3*lambda)>>(FF_LAMBDA_SHIFT+1);
 +    case FF_CMP_W53:
 +        return (4*lambda)>>(FF_LAMBDA_SHIFT);
 +    case FF_CMP_W97:
 +        return (2*lambda)>>(FF_LAMBDA_SHIFT);
 +    case FF_CMP_SATD:
 +    case FF_CMP_DCT264:
 +        return (2*lambda)>>FF_LAMBDA_SHIFT;
 +    case FF_CMP_RD:
 +    case FF_CMP_PSNR:
 +    case FF_CMP_SSE:
 +    case FF_CMP_NSSE:
 +        return lambda2>>FF_LAMBDA_SHIFT;
 +    case FF_CMP_BIT:
 +        return 1;
 +    }
 +}
 +
 +//FIXME copy&paste
 +#define P_LEFT P[1]
 +#define P_TOP P[2]
 +#define P_TOPRIGHT P[3]
 +#define P_MEDIAN P[4]
 +#define P_MV1 P[9]
 +#define FLAG_QPEL   1 //must be 1
 +
 +static int encode_q_branch(SnowContext *s, int level, int x, int y){
 +    uint8_t p_buffer[1024];
 +    uint8_t i_buffer[1024];
 +    uint8_t p_state[sizeof(s->block_state)];
 +    uint8_t i_state[sizeof(s->block_state)];
 +    RangeCoder pc, ic;
 +    uint8_t *pbbak= s->c.bytestream;
 +    uint8_t *pbbak_start= s->c.bytestream_start;
 +    int score, score2, iscore, i_len, p_len, block_s, sum, base_bits;
 +    const int w= s->b_width  << s->block_max_depth;
 +    const int h= s->b_height << s->block_max_depth;
 +    const int rem_depth= s->block_max_depth - level;
 +    const int index= (x + y*w) << rem_depth;
 +    const int block_w= 1<<(LOG2_MB_SIZE - level);
 +    int trx= (x+1)<<rem_depth;
 +    int try= (y+1)<<rem_depth;
 +    const BlockNode *left  = x ? &s->block[index-1] : &null_block;
 +    const BlockNode *top   = y ? &s->block[index-w] : &null_block;
 +    const BlockNode *right = trx<w ? &s->block[index+1] : &null_block;
 +    const BlockNode *bottom= try<h ? &s->block[index+w] : &null_block;
 +    const BlockNode *tl    = y && x ? &s->block[index-w-1] : left;
 +    const BlockNode *tr    = y && trx<w && ((x&1)==0 || level==0) ? &s->block[index-w+(1<<rem_depth)] : tl; //FIXME use lt
 +    int pl = left->color[0];
 +    int pcb= left->color[1];
 +    int pcr= left->color[2];
 +    int pmx, pmy;
 +    int mx=0, my=0;
 +    int l,cr,cb;
 +    const int stride= s->current_picture->linesize[0];
 +    const int uvstride= s->current_picture->linesize[1];
 +    uint8_t *current_data[3]= { s->input_picture->data[0] + (x + y*  stride)*block_w,
 +                                s->input_picture->data[1] + ((x*block_w)>>s->chroma_h_shift) + ((y*uvstride*block_w)>>s->chroma_v_shift),
 +                                s->input_picture->data[2] + ((x*block_w)>>s->chroma_h_shift) + ((y*uvstride*block_w)>>s->chroma_v_shift)};
 +    int P[10][2];
 +    int16_t last_mv[3][2];
 +    int qpel= !!(s->avctx->flags & CODEC_FLAG_QPEL); //unused
 +    const int shift= 1+qpel;
 +    MotionEstContext *c= &s->m.me;
 +    int ref_context= av_log2(2*left->ref) + av_log2(2*top->ref);
 +    int mx_context= av_log2(2*FFABS(left->mx - top->mx));
 +    int my_context= av_log2(2*FFABS(left->my - top->my));
 +    int s_context= 2*left->level + 2*top->level + tl->level + tr->level;
 +    int ref, best_ref, ref_score, ref_mx, ref_my;
 +
 +    av_assert0(sizeof(s->block_state) >= 256);
 +    if(s->keyframe){
 +        set_blocks(s, level, x, y, pl, pcb, pcr, 0, 0, 0, BLOCK_INTRA);
 +        return 0;
 +    }
 +
 +//    clip predictors / edge ?
 +
 +    P_LEFT[0]= left->mx;
 +    P_LEFT[1]= left->my;
 +    P_TOP [0]= top->mx;
 +    P_TOP [1]= top->my;
 +    P_TOPRIGHT[0]= tr->mx;
 +    P_TOPRIGHT[1]= tr->my;
 +
 +    last_mv[0][0]= s->block[index].mx;
 +    last_mv[0][1]= s->block[index].my;
 +    last_mv[1][0]= right->mx;
 +    last_mv[1][1]= right->my;
 +    last_mv[2][0]= bottom->mx;
 +    last_mv[2][1]= bottom->my;
 +
 +    s->m.mb_stride=2;
 +    s->m.mb_x=
 +    s->m.mb_y= 0;
 +    c->skip= 0;
 +
 +    av_assert1(c->  stride ==   stride);
 +    av_assert1(c->uvstride == uvstride);
 +
 +    c->penalty_factor    = get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_cmp);
 +    c->sub_penalty_factor= get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_sub_cmp);
 +    c->mb_penalty_factor = get_penalty_factor(s->lambda, s->lambda2, c->avctx->mb_cmp);
 +    c->current_mv_penalty= c->mv_penalty[s->m.f_code=1] + MAX_MV;
 +
 +    c->xmin = - x*block_w - 16+3;
 +    c->ymin = - y*block_w - 16+3;
 +    c->xmax = - (x+1)*block_w + (w<<(LOG2_MB_SIZE - s->block_max_depth)) + 16-3;
 +    c->ymax = - (y+1)*block_w + (h<<(LOG2_MB_SIZE - s->block_max_depth)) + 16-3;
 +
 +    if(P_LEFT[0]     > (c->xmax<<shift)) P_LEFT[0]    = (c->xmax<<shift);
 +    if(P_LEFT[1]     > (c->ymax<<shift)) P_LEFT[1]    = (c->ymax<<shift);
 +    if(P_TOP[0]      > (c->xmax<<shift)) P_TOP[0]     = (c->xmax<<shift);
 +    if(P_TOP[1]      > (c->ymax<<shift)) P_TOP[1]     = (c->ymax<<shift);
 +    if(P_TOPRIGHT[0] < (c->xmin<<shift)) P_TOPRIGHT[0]= (c->xmin<<shift);
 +    if(P_TOPRIGHT[0] > (c->xmax<<shift)) P_TOPRIGHT[0]= (c->xmax<<shift); //due to pmx no clip
 +    if(P_TOPRIGHT[1] > (c->ymax<<shift)) P_TOPRIGHT[1]= (c->ymax<<shift);
 +
 +    P_MEDIAN[0]= mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]);
 +    P_MEDIAN[1]= mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]);
 +
 +    if (!y) {
 +        c->pred_x= P_LEFT[0];
 +        c->pred_y= P_LEFT[1];
 +    } else {
 +        c->pred_x = P_MEDIAN[0];
 +        c->pred_y = P_MEDIAN[1];
 +    }
 +
 +    score= INT_MAX;
 +    best_ref= 0;
 +    for(ref=0; ref<s->ref_frames; ref++){
 +        init_ref(c, current_data, s->last_picture[ref]->data, NULL, block_w*x, block_w*y, 0);
 +
 +        ref_score= ff_epzs_motion_search(&s->m, &ref_mx, &ref_my, P, 0, /*ref_index*/ 0, last_mv,
 +                                         (1<<16)>>shift, level-LOG2_MB_SIZE+4, block_w);
 +
 +        av_assert2(ref_mx >= c->xmin);
 +        av_assert2(ref_mx <= c->xmax);
 +        av_assert2(ref_my >= c->ymin);
 +        av_assert2(ref_my <= c->ymax);
 +
 +        ref_score= c->sub_motion_search(&s->m, &ref_mx, &ref_my, ref_score, 0, 0, level-LOG2_MB_SIZE+4, block_w);
 +        ref_score= ff_get_mb_score(&s->m, ref_mx, ref_my, 0, 0, level-LOG2_MB_SIZE+4, block_w, 0);
 +        ref_score+= 2*av_log2(2*ref)*c->penalty_factor;
 +        if(s->ref_mvs[ref]){
 +            s->ref_mvs[ref][index][0]= ref_mx;
 +            s->ref_mvs[ref][index][1]= ref_my;
 +            s->ref_scores[ref][index]= ref_score;
 +        }
 +        if(score > ref_score){
 +            score= ref_score;
 +            best_ref= ref;
 +            mx= ref_mx;
 +            my= ref_my;
 +        }
 +    }
 +    //FIXME if mb_cmp != SSE then intra cannot be compared currently and mb_penalty vs. lambda2
 +
 +  //  subpel search
 +    base_bits= get_rac_count(&s->c) - 8*(s->c.bytestream - s->c.bytestream_start);
 +    pc= s->c;
 +    pc.bytestream_start=
 +    pc.bytestream= p_buffer; //FIXME end/start? and at the other stoo
 +    memcpy(p_state, s->block_state, sizeof(s->block_state));
 +
 +    if(level!=s->block_max_depth)
 +        put_rac(&pc, &p_state[4 + s_context], 1);
 +    put_rac(&pc, &p_state[1 + left->type + top->type], 0);
 +    if(s->ref_frames > 1)
 +        put_symbol(&pc, &p_state[128 + 1024 + 32*ref_context], best_ref, 0);
 +    pred_mv(s, &pmx, &pmy, best_ref, left, top, tr);
 +    put_symbol(&pc, &p_state[128 + 32*(mx_context + 16*!!best_ref)], mx - pmx, 1);
 +    put_symbol(&pc, &p_state[128 + 32*(my_context + 16*!!best_ref)], my - pmy, 1);
 +    p_len= pc.bytestream - pc.bytestream_start;
 +    score += (s->lambda2*(get_rac_count(&pc)-base_bits))>>FF_LAMBDA_SHIFT;
 +
 +    block_s= block_w*block_w;
 +    sum = pix_sum(current_data[0], stride, block_w, block_w);
 +    l= (sum + block_s/2)/block_s;
 +    iscore = pix_norm1(current_data[0], stride, block_w) - 2*l*sum + l*l*block_s;
 +
 +    if (s->nb_planes > 2) {
 +        block_s= block_w*block_w>>(s->chroma_h_shift + s->chroma_v_shift);
 +        sum = pix_sum(current_data[1], uvstride, block_w>>s->chroma_h_shift, block_w>>s->chroma_v_shift);
 +        cb= (sum + block_s/2)/block_s;
 +    //    iscore += pix_norm1(&current_mb[1][0], uvstride, block_w>>1) - 2*cb*sum + cb*cb*block_s;
 +        sum = pix_sum(current_data[2], uvstride, block_w>>s->chroma_h_shift, block_w>>s->chroma_v_shift);
 +        cr= (sum + block_s/2)/block_s;
 +    //    iscore += pix_norm1(&current_mb[2][0], uvstride, block_w>>1) - 2*cr*sum + cr*cr*block_s;
 +    }else
 +        cb = cr = 0;
 +
 +    ic= s->c;
 +    ic.bytestream_start=
 +    ic.bytestream= i_buffer; //FIXME end/start? and at the other stoo
 +    memcpy(i_state, s->block_state, sizeof(s->block_state));
 +    if(level!=s->block_max_depth)
 +        put_rac(&ic, &i_state[4 + s_context], 1);
 +    put_rac(&ic, &i_state[1 + left->type + top->type], 1);
 +    put_symbol(&ic, &i_state[32],  l-pl , 1);
 +    if (s->nb_planes > 2) {
 +        put_symbol(&ic, &i_state[64], cb-pcb, 1);
 +        put_symbol(&ic, &i_state[96], cr-pcr, 1);
 +    }
 +    i_len= ic.bytestream - ic.bytestream_start;
 +    iscore += (s->lambda2*(get_rac_count(&ic)-base_bits))>>FF_LAMBDA_SHIFT;
 +
 +//    assert(score==256*256*256*64-1);
 +    av_assert1(iscore < 255*255*256 + s->lambda2*10);
 +    av_assert1(iscore >= 0);
 +    av_assert1(l>=0 && l<=255);
 +    av_assert1(pl>=0 && pl<=255);
 +
 +    if(level==0){
 +        int varc= iscore >> 8;
 +        int vard= score >> 8;
 +        if (vard <= 64 || vard < varc)
 +            c->scene_change_score+= ff_sqrt(vard) - ff_sqrt(varc);
 +        else
 +            c->scene_change_score+= s->m.qscale;
 +    }
 +
 +    if(level!=s->block_max_depth){
 +        put_rac(&s->c, &s->block_state[4 + s_context], 0);
 +        score2 = encode_q_branch(s, level+1, 2*x+0, 2*y+0);
 +        score2+= encode_q_branch(s, level+1, 2*x+1, 2*y+0);
 +        score2+= encode_q_branch(s, level+1, 2*x+0, 2*y+1);
 +        score2+= encode_q_branch(s, level+1, 2*x+1, 2*y+1);
 +        score2+= s->lambda2>>FF_LAMBDA_SHIFT; //FIXME exact split overhead
 +
 +        if(score2 < score && score2 < iscore)
 +            return score2;
 +    }
 +
 +    if(iscore < score){
 +        pred_mv(s, &pmx, &pmy, 0, left, top, tr);
 +        memcpy(pbbak, i_buffer, i_len);
 +        s->c= ic;
 +        s->c.bytestream_start= pbbak_start;
 +        s->c.bytestream= pbbak + i_len;
 +        set_blocks(s, level, x, y, l, cb, cr, pmx, pmy, 0, BLOCK_INTRA);
 +        memcpy(s->block_state, i_state, sizeof(s->block_state));
 +        return iscore;
 +    }else{
 +        memcpy(pbbak, p_buffer, p_len);
 +        s->c= pc;
 +        s->c.bytestream_start= pbbak_start;
 +        s->c.bytestream= pbbak + p_len;
 +        set_blocks(s, level, x, y, pl, pcb, pcr, mx, my, best_ref, 0);
 +        memcpy(s->block_state, p_state, sizeof(s->block_state));
 +        return score;
 +    }
 +}
 +
 +static void encode_q_branch2(SnowContext *s, int level, int x, int y){
 +    const int w= s->b_width  << s->block_max_depth;
 +    const int rem_depth= s->block_max_depth - level;
 +    const int index= (x + y*w) << rem_depth;
 +    int trx= (x+1)<<rem_depth;
 +    BlockNode *b= &s->block[index];
 +    const BlockNode *left  = x ? &s->block[index-1] : &null_block;
 +    const BlockNode *top   = y ? &s->block[index-w] : &null_block;
 +    const BlockNode *tl    = y && x ? &s->block[index-w-1] : left;
 +    const BlockNode *tr    = y && trx<w && ((x&1)==0 || level==0) ? &s->block[index-w+(1<<rem_depth)] : tl; //FIXME use lt
 +    int pl = left->color[0];
 +    int pcb= left->color[1];
 +    int pcr= left->color[2];
 +    int pmx, pmy;
 +    int ref_context= av_log2(2*left->ref) + av_log2(2*top->ref);
 +    int mx_context= av_log2(2*FFABS(left->mx - top->mx)) + 16*!!b->ref;
 +    int my_context= av_log2(2*FFABS(left->my - top->my)) + 16*!!b->ref;
 +    int s_context= 2*left->level + 2*top->level + tl->level + tr->level;
 +
 +    if(s->keyframe){
 +        set_blocks(s, level, x, y, pl, pcb, pcr, 0, 0, 0, BLOCK_INTRA);
 +        return;
 +    }
 +
 +    if(level!=s->block_max_depth){
 +        if(same_block(b,b+1) && same_block(b,b+w) && same_block(b,b+w+1)){
 +            put_rac(&s->c, &s->block_state[4 + s_context], 1);
 +        }else{
 +            put_rac(&s->c, &s->block_state[4 + s_context], 0);
 +            encode_q_branch2(s, level+1, 2*x+0, 2*y+0);
 +            encode_q_branch2(s, level+1, 2*x+1, 2*y+0);
 +            encode_q_branch2(s, level+1, 2*x+0, 2*y+1);
 +            encode_q_branch2(s, level+1, 2*x+1, 2*y+1);
 +            return;
 +        }
 +    }
 +    if(b->type & BLOCK_INTRA){
 +        pred_mv(s, &pmx, &pmy, 0, left, top, tr);
 +        put_rac(&s->c, &s->block_state[1 + (left->type&1) + (top->type&1)], 1);
 +        put_symbol(&s->c, &s->block_state[32], b->color[0]-pl , 1);
 +        if (s->nb_planes > 2) {
 +            put_symbol(&s->c, &s->block_state[64], b->color[1]-pcb, 1);
 +            put_symbol(&s->c, &s->block_state[96], b->color[2]-pcr, 1);
 +        }
 +        set_blocks(s, level, x, y, b->color[0], b->color[1], b->color[2], pmx, pmy, 0, BLOCK_INTRA);
 +    }else{
 +        pred_mv(s, &pmx, &pmy, b->ref, left, top, tr);
 +        put_rac(&s->c, &s->block_state[1 + (left->type&1) + (top->type&1)], 0);
 +        if(s->ref_frames > 1)
 +            put_symbol(&s->c, &s->block_state[128 + 1024 + 32*ref_context], b->ref, 0);
 +        put_symbol(&s->c, &s->block_state[128 + 32*mx_context], b->mx - pmx, 1);
 +        put_symbol(&s->c, &s->block_state[128 + 32*my_context], b->my - pmy, 1);
 +        set_blocks(s, level, x, y, pl, pcb, pcr, b->mx, b->my, b->ref, 0);
 +    }
 +}
 +
 +static int get_dc(SnowContext *s, int mb_x, int mb_y, int plane_index){
 +    int i, x2, y2;
 +    Plane *p= &s->plane[plane_index];
 +    const int block_size = MB_SIZE >> s->block_max_depth;
 +    const int block_w    = plane_index ? block_size>>s->chroma_h_shift : block_size;
 +    const int block_h    = plane_index ? block_size>>s->chroma_v_shift : block_size;
 +    const uint8_t *obmc  = plane_index ? ff_obmc_tab[s->block_max_depth+s->chroma_h_shift] : ff_obmc_tab[s->block_max_depth];
 +    const int obmc_stride= plane_index ? (2*block_size)>>s->chroma_h_shift : 2*block_size;
 +    const int ref_stride= s->current_picture->linesize[plane_index];
 +    uint8_t *src= s-> input_picture->data[plane_index];
 +    IDWTELEM *dst= (IDWTELEM*)s->m.obmc_scratchpad + plane_index*block_size*block_size*4; //FIXME change to unsigned
 +    const int b_stride = s->b_width << s->block_max_depth;
 +    const int w= p->width;
 +    const int h= p->height;
 +    int index= mb_x + mb_y*b_stride;
 +    BlockNode *b= &s->block[index];
 +    BlockNode backup= *b;
 +    int ab=0;
 +    int aa=0;
 +
 +    av_assert2(s->chroma_h_shift == s->chroma_v_shift); //obmc stuff above
 +
 +    b->type|= BLOCK_INTRA;
 +    b->color[plane_index]= 0;
 +    memset(dst, 0, obmc_stride*obmc_stride*sizeof(IDWTELEM));
 +
 +    for(i=0; i<4; i++){
 +        int mb_x2= mb_x + (i &1) - 1;
 +        int mb_y2= mb_y + (i>>1) - 1;
 +        int x= block_w*mb_x2 + block_w/2;
 +        int y= block_h*mb_y2 + block_h/2;
 +
 +        add_yblock(s, 0, NULL, dst + (i&1)*block_w + (i>>1)*obmc_stride*block_h, NULL, obmc,
 +                    x, y, block_w, block_h, w, h, obmc_stride, ref_stride, obmc_stride, mb_x2, mb_y2, 0, 0, plane_index);
 +
 +        for(y2= FFMAX(y, 0); y2<FFMIN(h, y+block_h); y2++){
 +            for(x2= FFMAX(x, 0); x2<FFMIN(w, x+block_w); x2++){
 +                int index= x2-(block_w*mb_x - block_w/2) + (y2-(block_h*mb_y - block_h/2))*obmc_stride;
 +                int obmc_v= obmc[index];
 +                int d;
 +                if(y<0) obmc_v += obmc[index + block_h*obmc_stride];
 +                if(x<0) obmc_v += obmc[index + block_w];
 +                if(y+block_h>h) obmc_v += obmc[index - block_h*obmc_stride];
 +                if(x+block_w>w) obmc_v += obmc[index - block_w];
 +                //FIXME precalculate this or simplify it somehow else
 +
 +                d = -dst[index] + (1<<(FRAC_BITS-1));
 +                dst[index] = d;
 +                ab += (src[x2 + y2*ref_stride] - (d>>FRAC_BITS)) * obmc_v;
 +                aa += obmc_v * obmc_v; //FIXME precalculate this
 +            }
 +        }
 +    }
 +    *b= backup;
 +
 +    return av_clip( ROUNDED_DIV(ab<<LOG2_OBMC_MAX, aa), 0, 255); //FIXME we should not need clipping
 +}
 +
 +static inline int get_block_bits(SnowContext *s, int x, int y, int w){
 +    const int b_stride = s->b_width << s->block_max_depth;
 +    const int b_height = s->b_height<< s->block_max_depth;
 +    int index= x + y*b_stride;
 +    const BlockNode *b     = &s->block[index];
 +    const BlockNode *left  = x ? &s->block[index-1] : &null_block;
 +    const BlockNode *top   = y ? &s->block[index-b_stride] : &null_block;
 +    const BlockNode *tl    = y && x ? &s->block[index-b_stride-1] : left;
 +    const BlockNode *tr    = y && x+w<b_stride ? &s->block[index-b_stride+w] : tl;
 +    int dmx, dmy;
 +//  int mx_context= av_log2(2*FFABS(left->mx - top->mx));
 +//  int my_context= av_log2(2*FFABS(left->my - top->my));
 +
 +    if(x<0 || x>=b_stride || y>=b_height)
 +        return 0;
 +/*
 +1            0      0
 +01X          1-2    1
 +001XX        3-6    2-3
 +0001XXX      7-14   4-7
 +00001XXXX   15-30   8-15
 +*/
 +//FIXME try accurate rate
 +//FIXME intra and inter predictors if surrounding blocks are not the same type
 +    if(b->type & BLOCK_INTRA){
 +        return 3+2*( av_log2(2*FFABS(left->color[0] - b->color[0]))
 +                   + av_log2(2*FFABS(left->color[1] - b->color[1]))
 +                   + av_log2(2*FFABS(left->color[2] - b->color[2])));
 +    }else{
 +        pred_mv(s, &dmx, &dmy, b->ref, left, top, tr);
 +        dmx-= b->mx;
 +        dmy-= b->my;
 +        return 2*(1 + av_log2(2*FFABS(dmx)) //FIXME kill the 2* can be merged in lambda
 +                    + av_log2(2*FFABS(dmy))
 +                    + av_log2(2*b->ref));
 +    }
 +}
 +
 +static int get_block_rd(SnowContext *s, int mb_x, int mb_y, int plane_index, uint8_t (*obmc_edged)[MB_SIZE * 2]){
 +    Plane *p= &s->plane[plane_index];
 +    const int block_size = MB_SIZE >> s->block_max_depth;
 +    const int block_w    = plane_index ? block_size>>s->chroma_h_shift : block_size;
 +    const int block_h    = plane_index ? block_size>>s->chroma_v_shift : block_size;
 +    const int obmc_stride= plane_index ? (2*block_size)>>s->chroma_h_shift : 2*block_size;
 +    const int ref_stride= s->current_picture->linesize[plane_index];
 +    uint8_t *dst= s->current_picture->data[plane_index];
 +    uint8_t *src= s->  input_picture->data[plane_index];
 +    IDWTELEM *pred= (IDWTELEM*)s->m.obmc_scratchpad + plane_index*block_size*block_size*4;
 +    uint8_t *cur = s->scratchbuf;
 +    uint8_t *tmp = s->emu_edge_buffer;
 +    const int b_stride = s->b_width << s->block_max_depth;
 +    const int b_height = s->b_height<< s->block_max_depth;
 +    const int w= p->width;
 +    const int h= p->height;
 +    int distortion;
 +    int rate= 0;
 +    const int penalty_factor= get_penalty_factor(s->lambda, s->lambda2, s->avctx->me_cmp);
 +    int sx= block_w*mb_x - block_w/2;
 +    int sy= block_h*mb_y - block_h/2;
 +    int x0= FFMAX(0,-sx);
 +    int y0= FFMAX(0,-sy);
 +    int x1= FFMIN(block_w*2, w-sx);
 +    int y1= FFMIN(block_h*2, h-sy);
 +    int i,x,y;
 +
 +    av_assert2(s->chroma_h_shift == s->chroma_v_shift); //obmc and square assumtions below chckinhg only block_w
 +
 +    ff_snow_pred_block(s, cur, tmp, ref_stride, sx, sy, block_w*2, block_h*2, &s->block[mb_x + mb_y*b_stride], plane_index, w, h);
 +
 +    for(y=y0; y<y1; y++){
 +        const uint8_t *obmc1= obmc_edged[y];
 +        const IDWTELEM *pred1 = pred + y*obmc_stride;
 +        uint8_t *cur1 = cur + y*ref_stride;
 +        uint8_t *dst1 = dst + sx + (sy+y)*ref_stride;
 +        for(x=x0; x<x1; x++){
 +#if FRAC_BITS >= LOG2_OBMC_MAX
 +            int v = (cur1[x] * obmc1[x]) << (FRAC_BITS - LOG2_OBMC_MAX);
 +#else
 +            int v = (cur1[x] * obmc1[x] + (1<<(LOG2_OBMC_MAX - FRAC_BITS-1))) >> (LOG2_OBMC_MAX - FRAC_BITS);
 +#endif
 +            v = (v + pred1[x]) >> FRAC_BITS;
 +            if(v&(~255)) v= ~(v>>31);
 +            dst1[x] = v;
 +        }
 +    }
 +
 +    /* copy the regions where obmc[] = (uint8_t)256 */
 +    if(LOG2_OBMC_MAX == 8
 +        && (mb_x == 0 || mb_x == b_stride-1)
 +        && (mb_y == 0 || mb_y == b_height-1)){
 +        if(mb_x == 0)
 +            x1 = block_w;
 +        else
 +            x0 = block_w;
 +        if(mb_y == 0)
 +            y1 = block_h;
 +        else
 +            y0 = block_h;
 +        for(y=y0; y<y1; y++)
 +            memcpy(dst + sx+x0 + (sy+y)*ref_stride, cur + x0 + y*ref_stride, x1-x0);
 +    }
 +
 +    if(block_w==16){
 +        /* FIXME rearrange dsputil to fit 32x32 cmp functions */
 +        /* FIXME check alignment of the cmp wavelet vs the encoding wavelet */
 +        /* FIXME cmps overlap but do not cover the wavelet's whole support.
 +         * So improving the score of one block is not strictly guaranteed
 +         * to improve the score of the whole frame, thus iterative motion
 +         * estimation does not always converge. */
 +        if(s->avctx->me_cmp == FF_CMP_W97)
 +            distortion = ff_w97_32_c(&s->m, src + sx + sy*ref_stride, dst + sx + sy*ref_stride, ref_stride, 32);
 +        else if(s->avctx->me_cmp == FF_CMP_W53)
 +            distortion = ff_w53_32_c(&s->m, src + sx + sy*ref_stride, dst + sx + sy*ref_stride, ref_stride, 32);
 +        else{
 +            distortion = 0;
 +            for(i=0; i<4; i++){
 +                int off = sx+16*(i&1) + (sy+16*(i>>1))*ref_stride;
-         distortion = s->dsp.me_cmp[0](&s->m, src + sx + sy*ref_stride, dst + sx + sy*ref_stride, ref_stride, block_w*2);
++                distortion += s->mecc.me_cmp[0](&s->m, src + off, dst + off, ref_stride, 16);
 +            }
 +        }
 +    }else{
 +        av_assert2(block_w==8);
-         distortion += s->dsp.me_cmp[block_w==8](&s->m, src + x + y*ref_stride, dst + x + y*ref_stride, ref_stride, block_h);
++        distortion = s->mecc.me_cmp[0](&s->m, src + sx + sy*ref_stride, dst + sx + sy*ref_stride, ref_stride, block_w*2);
 +    }
 +
 +    if(plane_index==0){
 +        for(i=0; i<4; i++){
 +/* ..RRr
 + * .RXx.
 + * rxx..
 + */
 +            rate += get_block_bits(s, mb_x + (i&1) - (i>>1), mb_y + (i>>1), 1);
 +        }
 +        if(mb_x == b_stride-2)
 +            rate += get_block_bits(s, mb_x + 1, mb_y + 1, 1);
 +    }
 +    return distortion + rate*penalty_factor;
 +}
 +
 +static int get_4block_rd(SnowContext *s, int mb_x, int mb_y, int plane_index){
 +    int i, y2;
 +    Plane *p= &s->plane[plane_index];
 +    const int block_size = MB_SIZE >> s->block_max_depth;
 +    const int block_w    = plane_index ? block_size>>s->chroma_h_shift : block_size;
 +    const int block_h    = plane_index ? block_size>>s->chroma_v_shift : block_size;
 +    const uint8_t *obmc  = plane_index ? ff_obmc_tab[s->block_max_depth+s->chroma_h_shift] : ff_obmc_tab[s->block_max_depth];
 +    const int obmc_stride= plane_index ? (2*block_size)>>s->chroma_h_shift : 2*block_size;
 +    const int ref_stride= s->current_picture->linesize[plane_index];
 +    uint8_t *dst= s->current_picture->data[plane_index];
 +    uint8_t *src= s-> input_picture->data[plane_index];
 +    //FIXME zero_dst is const but add_yblock changes dst if add is 0 (this is never the case for dst=zero_dst
 +    // const has only been removed from zero_dst to suppress a warning
 +    static IDWTELEM zero_dst[4096]; //FIXME
 +    const int b_stride = s->b_width << s->block_max_depth;
 +    const int w= p->width;
 +    const int h= p->height;
 +    int distortion= 0;
 +    int rate= 0;
 +    const int penalty_factor= get_penalty_factor(s->lambda, s->lambda2, s->avctx->me_cmp);
 +
 +    av_assert2(s->chroma_h_shift == s->chroma_v_shift); //obmc and square assumtions below
 +
 +    for(i=0; i<9; i++){
 +        int mb_x2= mb_x + (i%3) - 1;
 +        int mb_y2= mb_y + (i/3) - 1;
 +        int x= block_w*mb_x2 + block_w/2;
 +        int y= block_h*mb_y2 + block_h/2;
 +
 +        add_yblock(s, 0, NULL, zero_dst, dst, obmc,
 +                   x, y, block_w, block_h, w, h, /*dst_stride*/0, ref_stride, obmc_stride, mb_x2, mb_y2, 1, 1, plane_index);
 +
 +        //FIXME find a cleaner/simpler way to skip the outside stuff
 +        for(y2= y; y2<0; y2++)
 +            memcpy(dst + x + y2*ref_stride, src + x + y2*ref_stride, block_w);
 +        for(y2= h; y2<y+block_h; y2++)
 +            memcpy(dst + x + y2*ref_stride, src + x + y2*ref_stride, block_w);
 +        if(x<0){
 +            for(y2= y; y2<y+block_h; y2++)
 +                memcpy(dst + x + y2*ref_stride, src + x + y2*ref_stride, -x);
 +        }
 +        if(x+block_w > w){
 +            for(y2= y; y2<y+block_h; y2++)
 +                memcpy(dst + w + y2*ref_stride, src + w + y2*ref_stride, x+block_w - w);
 +        }
 +
 +        av_assert1(block_w== 8 || block_w==16);
-         s->m.dsp= s->dsp; //move
++        distortion += s->mecc.me_cmp[block_w==8](&s->m, src + x + y*ref_stride, dst + x + y*ref_stride, ref_stride, block_h);
 +    }
 +
 +    if(plane_index==0){
 +        BlockNode *b= &s->block[mb_x+mb_y*b_stride];
 +        int merged= same_block(b,b+1) && same_block(b,b+b_stride) && same_block(b,b+b_stride+1);
 +
 +/* ..RRRr
 + * .RXXx.
 + * .RXXx.
 + * rxxx.
 + */
 +        if(merged)
 +            rate = get_block_bits(s, mb_x, mb_y, 2);
 +        for(i=merged?4:0; i<9; i++){
 +            static const int dxy[9][2] = {{0,0},{1,0},{0,1},{1,1},{2,0},{2,1},{-1,2},{0,2},{1,2}};
 +            rate += get_block_bits(s, mb_x + dxy[i][0], mb_y + dxy[i][1], 1);
 +        }
 +    }
 +    return distortion + rate*penalty_factor;
 +}
 +
 +static int encode_subband_c0run(SnowContext *s, SubBand *b, const IDWTELEM *src, const IDWTELEM *parent, int stride, int orientation){
 +    const int w= b->width;
 +    const int h= b->height;
 +    int x, y;
 +
 +    if(1){
 +        int run=0;
 +        int *runs = s->run_buffer;
 +        int run_index=0;
 +        int max_index;
 +
 +        for(y=0; y<h; y++){
 +            for(x=0; x<w; x++){
 +                int v, p=0;
 +                int /*ll=0, */l=0, lt=0, t=0, rt=0;
 +                v= src[x + y*stride];
 +
 +                if(y){
 +                    t= src[x + (y-1)*stride];
 +                    if(x){
 +                        lt= src[x - 1 + (y-1)*stride];
 +                    }
 +                    if(x + 1 < w){
 +                        rt= src[x + 1 + (y-1)*stride];
 +                    }
 +                }
 +                if(x){
 +                    l= src[x - 1 + y*stride];
 +                    /*if(x > 1){
 +                        if(orientation==1) ll= src[y + (x-2)*stride];
 +                        else               ll= src[x - 2 + y*stride];
 +                    }*/
 +                }
 +                if(parent){
 +                    int px= x>>1;
 +                    int py= y>>1;
 +                    if(px<b->parent->width && py<b->parent->height)
 +                        p= parent[px + py*2*stride];
 +                }
 +                if(!(/*ll|*/l|lt|t|rt|p)){
 +                    if(v){
 +                        runs[run_index++]= run;
 +                        run=0;
 +                    }else{
 +                        run++;
 +                    }
 +                }
 +            }
 +        }
 +        max_index= run_index;
 +        runs[run_index++]= run;
 +        run_index=0;
 +        run= runs[run_index++];
 +
 +        put_symbol2(&s->c, b->state[30], max_index, 0);
 +        if(run_index <= max_index)
 +            put_symbol2(&s->c, b->state[1], run, 3);
 +
 +        for(y=0; y<h; y++){
 +            if(s->c.bytestream_end - s->c.bytestream < w*40){
 +                av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n");
 +                return -1;
 +            }
 +            for(x=0; x<w; x++){
 +                int v, p=0;
 +                int /*ll=0, */l=0, lt=0, t=0, rt=0;
 +                v= src[x + y*stride];
 +
 +                if(y){
 +                    t= src[x + (y-1)*stride];
 +                    if(x){
 +                        lt= src[x - 1 + (y-1)*stride];
 +                    }
 +                    if(x + 1 < w){
 +                        rt= src[x + 1 + (y-1)*stride];
 +                    }
 +                }
 +                if(x){
 +                    l= src[x - 1 + y*stride];
 +                    /*if(x > 1){
 +                        if(orientation==1) ll= src[y + (x-2)*stride];
 +                        else               ll= src[x - 2 + y*stride];
 +                    }*/
 +                }
 +                if(parent){
 +                    int px= x>>1;
 +                    int py= y>>1;
 +                    if(px<b->parent->width && py<b->parent->height)
 +                        p= parent[px + py*2*stride];
 +                }
 +                if(/*ll|*/l|lt|t|rt|p){
 +                    int context= av_log2(/*FFABS(ll) + */3*FFABS(l) + FFABS(lt) + 2*FFABS(t) + FFABS(rt) + FFABS(p));
 +
 +                    put_rac(&s->c, &b->state[0][context], !!v);
 +                }else{
 +                    if(!run){
 +                        run= runs[run_index++];
 +
 +                        if(run_index <= max_index)
 +                            put_symbol2(&s->c, b->state[1], run, 3);
 +                        av_assert2(v);
 +                    }else{
 +                        run--;
 +                        av_assert2(!v);
 +                    }
 +                }
 +                if(v){
 +                    int context= av_log2(/*FFABS(ll) + */3*FFABS(l) + FFABS(lt) + 2*FFABS(t) + FFABS(rt) + FFABS(p));
 +                    int l2= 2*FFABS(l) + (l<0);
 +                    int t2= 2*FFABS(t) + (t<0);
 +
 +                    put_symbol2(&s->c, b->state[context + 2], FFABS(v)-1, context-4);
 +                    put_rac(&s->c, &b->state[0][16 + 1 + 3 + ff_quant3bA[l2&0xFF] + 3*ff_quant3bA[t2&0xFF]], v<0);
 +                }
 +            }
 +        }
 +    }
 +    return 0;
 +}
 +
 +static int encode_subband(SnowContext *s, SubBand *b, const IDWTELEM *src, const IDWTELEM *parent, int stride, int orientation){
 +//    encode_subband_qtree(s, b, src, parent, stride, orientation);
 +//    encode_subband_z0run(s, b, src, parent, stride, orientation);
 +    return encode_subband_c0run(s, b, src, parent, stride, orientation);
 +//    encode_subband_dzr(s, b, src, parent, stride, orientation);
 +}
 +
 +static av_always_inline int check_block(SnowContext *s, int mb_x, int mb_y, int p[3], int intra, uint8_t (*obmc_edged)[MB_SIZE * 2], int *best_rd){
 +    const int b_stride= s->b_width << s->block_max_depth;
 +    BlockNode *block= &s->block[mb_x + mb_y * b_stride];
 +    BlockNode backup= *block;
 +    unsigned value;
 +    int rd, index;
 +
 +    av_assert2(mb_x>=0 && mb_y>=0);
 +    av_assert2(mb_x<b_stride);
 +
 +    if(intra){
 +        block->color[0] = p[0];
 +        block->color[1] = p[1];
 +        block->color[2] = p[2];
 +        block->type |= BLOCK_INTRA;
 +    }else{
 +        index= (p[0] + 31*p[1]) & (ME_CACHE_SIZE-1);
 +        value= s->me_cache_generation + (p[0]>>10) + (p[1]<<6) + (block->ref<<12);
 +        if(s->me_cache[index] == value)
 +            return 0;
 +        s->me_cache[index]= value;
 +
 +        block->mx= p[0];
 +        block->my= p[1];
 +        block->type &= ~BLOCK_INTRA;
 +    }
 +
 +    rd= get_block_rd(s, mb_x, mb_y, 0, obmc_edged);
 +
 +//FIXME chroma
 +    if(rd < *best_rd){
 +        *best_rd= rd;
 +        return 1;
 +    }else{
 +        *block= backup;
 +        return 0;
 +    }
 +}
 +
 +/* special case for int[2] args we discard afterwards,
 + * fixes compilation problem with gcc 2.95 */
 +static av_always_inline int check_block_inter(SnowContext *s, int mb_x, int mb_y, int p0, int p1, uint8_t (*obmc_edged)[MB_SIZE * 2], int *best_rd){
 +    int p[2] = {p0, p1};
 +    return check_block(s, mb_x, mb_y, p, 0, obmc_edged, best_rd);
 +}
 +
 +static av_always_inline int check_4block_inter(SnowContext *s, int mb_x, int mb_y, int p0, int p1, int ref, int *best_rd){
 +    const int b_stride= s->b_width << s->block_max_depth;
 +    BlockNode *block= &s->block[mb_x + mb_y * b_stride];
 +    BlockNode backup[4];
 +    unsigned value;
 +    int rd, index;
 +
 +    /* We don't initialize backup[] during variable declaration, because
 +     * that fails to compile on MSVC: "cannot convert from 'BlockNode' to
 +     * 'int16_t'". */
 +    backup[0] = block[0];
 +    backup[1] = block[1];
 +    backup[2] = block[b_stride];
 +    backup[3] = block[b_stride + 1];
 +
 +    av_assert2(mb_x>=0 && mb_y>=0);
 +    av_assert2(mb_x<b_stride);
 +    av_assert2(((mb_x|mb_y)&1) == 0);
 +
 +    index= (p0 + 31*p1) & (ME_CACHE_SIZE-1);
 +    value= s->me_cache_generation + (p0>>10) + (p1<<6) + (block->ref<<12);
 +    if(s->me_cache[index] == value)
 +        return 0;
 +    s->me_cache[index]= value;
 +
 +    block->mx= p0;
 +    block->my= p1;
 +    block->ref= ref;
 +    block->type &= ~BLOCK_INTRA;
 +    block[1]= block[b_stride]= block[b_stride+1]= *block;
 +
 +    rd= get_4block_rd(s, mb_x, mb_y, 0);
 +
 +//FIXME chroma
 +    if(rd < *best_rd){
 +        *best_rd= rd;
 +        return 1;
 +    }else{
 +        block[0]= backup[0];
 +        block[1]= backup[1];
 +        block[b_stride]= backup[2];
 +        block[b_stride+1]= backup[3];
 +        return 0;
 +    }
 +}
 +
 +static void iterative_me(SnowContext *s){
 +    int pass, mb_x, mb_y;
 +    const int b_width = s->b_width  << s->block_max_depth;
 +    const int b_height= s->b_height << s->block_max_depth;
 +    const int b_stride= b_width;
 +    int color[3];
 +
 +    {
 +        RangeCoder r = s->c;
 +        uint8_t state[sizeof(s->block_state)];
 +        memcpy(state, s->block_state, sizeof(s->block_state));
 +        for(mb_y= 0; mb_y<s->b_height; mb_y++)
 +            for(mb_x= 0; mb_x<s->b_width; mb_x++)
 +                encode_q_branch(s, 0, mb_x, mb_y);
 +        s->c = r;
 +        memcpy(s->block_state, state, sizeof(s->block_state));
 +    }
 +
 +    for(pass=0; pass<25; pass++){
 +        int change= 0;
 +
 +        for(mb_y= 0; mb_y<b_height; mb_y++){
 +            for(mb_x= 0; mb_x<b_width; mb_x++){
 +                int dia_change, i, j, ref;
 +                int best_rd= INT_MAX, ref_rd;
 +                BlockNode backup, ref_b;
 +                const int index= mb_x + mb_y * b_stride;
 +                BlockNode *block= &s->block[index];
 +                BlockNode *tb =                   mb_y            ? &s->block[index-b_stride  ] : NULL;
 +                BlockNode *lb = mb_x                              ? &s->block[index         -1] : NULL;
 +                BlockNode *rb = mb_x+1<b_width                    ? &s->block[index         +1] : NULL;
 +                BlockNode *bb =                   mb_y+1<b_height ? &s->block[index+b_stride  ] : NULL;
 +                BlockNode *tlb= mb_x           && mb_y            ? &s->block[index-b_stride-1] : NULL;
 +                BlockNode *trb= mb_x+1<b_width && mb_y            ? &s->block[index-b_stride+1] : NULL;
 +                BlockNode *blb= mb_x           && mb_y+1<b_height ? &s->block[index+b_stride-1] : NULL;
 +                BlockNode *brb= mb_x+1<b_width && mb_y+1<b_height ? &s->block[index+b_stride+1] : NULL;
 +                const int b_w= (MB_SIZE >> s->block_max_depth);
 +                uint8_t obmc_edged[MB_SIZE * 2][MB_SIZE * 2];
 +
 +                if(pass && (block->type & BLOCK_OPT))
 +                    continue;
 +                block->type |= BLOCK_OPT;
 +
 +                backup= *block;
 +
 +                if(!s->me_cache_generation)
 +                    memset(s->me_cache, 0, sizeof(s->me_cache));
 +                s->me_cache_generation += 1<<22;
 +
 +                //FIXME precalculate
 +                {
 +                    int x, y;
 +                    for (y = 0; y < b_w * 2; y++)
 +                        memcpy(obmc_edged[y], ff_obmc_tab[s->block_max_depth] + y * b_w * 2, b_w * 2);
 +                    if(mb_x==0)
 +                        for(y=0; y<b_w*2; y++)
 +                            memset(obmc_edged[y], obmc_edged[y][0] + obmc_edged[y][b_w-1], b_w);
 +                    if(mb_x==b_stride-1)
 +                        for(y=0; y<b_w*2; y++)
 +                            memset(obmc_edged[y]+b_w, obmc_edged[y][b_w] + obmc_edged[y][b_w*2-1], b_w);
 +                    if(mb_y==0){
 +                        for(x=0; x<b_w*2; x++)
 +                            obmc_edged[0][x] += obmc_edged[b_w-1][x];
 +                        for(y=1; y<b_w; y++)
 +                            memcpy(obmc_edged[y], obmc_edged[0], b_w*2);
 +                    }
 +                    if(mb_y==b_height-1){
 +                        for(x=0; x<b_w*2; x++)
 +                            obmc_edged[b_w*2-1][x] += obmc_edged[b_w][x];
 +                        for(y=b_w; y<b_w*2-1; y++)
 +                            memcpy(obmc_edged[y], obmc_edged[b_w*2-1], b_w*2);
 +                    }
 +                }
 +
 +                //skip stuff outside the picture
 +                if(mb_x==0 || mb_y==0 || mb_x==b_width-1 || mb_y==b_height-1){
 +                    uint8_t *src= s->  input_picture->data[0];
 +                    uint8_t *dst= s->current_picture->data[0];
 +                    const int stride= s->current_picture->linesize[0];
 +                    const int block_w= MB_SIZE >> s->block_max_depth;
 +                    const int block_h= MB_SIZE >> s->block_max_depth;
 +                    const int sx= block_w*mb_x - block_w/2;
 +                    const int sy= block_h*mb_y - block_h/2;
 +                    const int w= s->plane[0].width;
 +                    const int h= s->plane[0].height;
 +                    int y;
 +
 +                    for(y=sy; y<0; y++)
 +                        memcpy(dst + sx + y*stride, src + sx + y*stride, block_w*2);
 +                    for(y=h; y<sy+block_h*2; y++)
 +                        memcpy(dst + sx + y*stride, src + sx + y*stride, block_w*2);
 +                    if(sx<0){
 +                        for(y=sy; y<sy+block_h*2; y++)
 +                            memcpy(dst + sx + y*stride, src + sx + y*stride, -sx);
 +                    }
 +                    if(sx+block_w*2 > w){
 +                        for(y=sy; y<sy+block_h*2; y++)
 +                            memcpy(dst + w + y*stride, src + w + y*stride, sx+block_w*2 - w);
 +                    }
 +                }
 +
 +                // intra(black) = neighbors' contribution to the current block
 +                for(i=0; i < s->nb_planes; i++)
 +                    color[i]= get_dc(s, mb_x, mb_y, i);
 +
 +                // get previous score (cannot be cached due to OBMC)
 +                if(pass > 0 && (block->type&BLOCK_INTRA)){
 +                    int color0[3]= {block->color[0], block->color[1], block->color[2]};
 +                    check_block(s, mb_x, mb_y, color0, 1, obmc_edged, &best_rd);
 +                }else
 +                    check_block_inter(s, mb_x, mb_y, block->mx, block->my, obmc_edged, &best_rd);
 +
 +                ref_b= *block;
 +                ref_rd= best_rd;
 +                for(ref=0; ref < s->ref_frames; ref++){
 +                    int16_t (*mvr)[2]= &s->ref_mvs[ref][index];
 +                    if(s->ref_scores[ref][index] > s->ref_scores[ref_b.ref][index]*3/2) //FIXME tune threshold
 +                        continue;
 +                    block->ref= ref;
 +                    best_rd= INT_MAX;
 +
 +                    check_block_inter(s, mb_x, mb_y, mvr[0][0], mvr[0][1], obmc_edged, &best_rd);
 +                    check_block_inter(s, mb_x, mb_y, 0, 0, obmc_edged, &best_rd);
 +                    if(tb)
 +                        check_block_inter(s, mb_x, mb_y, mvr[-b_stride][0], mvr[-b_stride][1], obmc_edged, &best_rd);
 +                    if(lb)
 +                        check_block_inter(s, mb_x, mb_y, mvr[-1][0], mvr[-1][1], obmc_edged, &best_rd);
 +                    if(rb)
 +                        check_block_inter(s, mb_x, mb_y, mvr[1][0], mvr[1][1], obmc_edged, &best_rd);
 +                    if(bb)
 +                        check_block_inter(s, mb_x, mb_y, mvr[b_stride][0], mvr[b_stride][1], obmc_edged, &best_rd);
 +
 +                    /* fullpel ME */
 +                    //FIXME avoid subpel interpolation / round to nearest integer
 +                    do{
 +                        dia_change=0;
 +                        for(i=0; i<FFMAX(s->avctx->dia_size, 1); i++){
 +                            for(j=0; j<i; j++){
 +                                dia_change |= check_block_inter(s, mb_x, mb_y, block->mx+4*(i-j), block->my+(4*j), obmc_edged, &best_rd);
 +                                dia_change |= check_block_inter(s, mb_x, mb_y, block->mx-4*(i-j), block->my-(4*j), obmc_edged, &best_rd);
 +                                dia_change |= check_block_inter(s, mb_x, mb_y, block->mx+4*(i-j), block->my-(4*j), obmc_edged, &best_rd);
 +                                dia_change |= check_block_inter(s, mb_x, mb_y, block->mx-4*(i-j), block->my+(4*j), obmc_edged, &best_rd);
 +                            }
 +                        }
 +                    }while(dia_change);
 +                    /* subpel ME */
 +                    do{
 +                        static const int square[8][2]= {{+1, 0},{-1, 0},{ 0,+1},{ 0,-1},{+1,+1},{-1,-1},{+1,-1},{-1,+1},};
 +                        dia_change=0;
 +                        for(i=0; i<8; i++)
 +                            dia_change |= check_block_inter(s, mb_x, mb_y, block->mx+square[i][0], block->my+square[i][1], obmc_edged, &best_rd);
 +                    }while(dia_change);
 +                    //FIXME or try the standard 2 pass qpel or similar
 +
 +                    mvr[0][0]= block->mx;
 +                    mvr[0][1]= block->my;
 +                    if(ref_rd > best_rd){
 +                        ref_rd= best_rd;
 +                        ref_b= *block;
 +                    }
 +                }
 +                best_rd= ref_rd;
 +                *block= ref_b;
 +                check_block(s, mb_x, mb_y, color, 1, obmc_edged, &best_rd);
 +                //FIXME RD style color selection
 +                if(!same_block(block, &backup)){
 +                    if(tb ) tb ->type &= ~BLOCK_OPT;
 +                    if(lb ) lb ->type &= ~BLOCK_OPT;
 +                    if(rb ) rb ->type &= ~BLOCK_OPT;
 +                    if(bb ) bb ->type &= ~BLOCK_OPT;
 +                    if(tlb) tlb->type &= ~BLOCK_OPT;
 +                    if(trb) trb->type &= ~BLOCK_OPT;
 +                    if(blb) blb->type &= ~BLOCK_OPT;
 +                    if(brb) brb->type &= ~BLOCK_OPT;
 +                    change ++;
 +                }
 +            }
 +        }
 +        av_log(s->avctx, AV_LOG_ERROR, "pass:%d changed:%d\n", pass, change);
 +        if(!change)
 +            break;
 +    }
 +
 +    if(s->block_max_depth == 1){
 +        int change= 0;
 +        for(mb_y= 0; mb_y<b_height; mb_y+=2){
 +            for(mb_x= 0; mb_x<b_width; mb_x+=2){
 +                int i;
 +                int best_rd, init_rd;
 +                const int index= mb_x + mb_y * b_stride;
 +                BlockNode *b[4];
 +
 +                b[0]= &s->block[index];
 +                b[1]= b[0]+1;
 +                b[2]= b[0]+b_stride;
 +                b[3]= b[2]+1;
 +                if(same_block(b[0], b[1]) &&
 +                   same_block(b[0], b[2]) &&
 +                   same_block(b[0], b[3]))
 +                    continue;
 +
 +                if(!s->me_cache_generation)
 +                    memset(s->me_cache, 0, sizeof(s->me_cache));
 +                s->me_cache_generation += 1<<22;
 +
 +                init_rd= best_rd= get_4block_rd(s, mb_x, mb_y, 0);
 +
 +                //FIXME more multiref search?
 +                check_4block_inter(s, mb_x, mb_y,
 +                                   (b[0]->mx + b[1]->mx + b[2]->mx + b[3]->mx + 2) >> 2,
 +                                   (b[0]->my + b[1]->my + b[2]->my + b[3]->my + 2) >> 2, 0, &best_rd);
 +
 +                for(i=0; i<4; i++)
 +                    if(!(b[i]->type&BLOCK_INTRA))
 +                        check_4block_inter(s, mb_x, mb_y, b[i]->mx, b[i]->my, b[i]->ref, &best_rd);
 +
 +                if(init_rd != best_rd)
 +                    change++;
 +            }
 +        }
 +        av_log(s->avctx, AV_LOG_ERROR, "pass:4mv changed:%d\n", change*4);
 +    }
 +}
 +
 +static void encode_blocks(SnowContext *s, int search){
 +    int x, y;
 +    int w= s->b_width;
 +    int h= s->b_height;
 +
 +    if(s->avctx->me_method == ME_ITER && !s->keyframe && search)
 +        iterative_me(s);
 +
 +    for(y=0; y<h; y++){
 +        if(s->c.bytestream_end - s->c.bytestream < w*MB_SIZE*MB_SIZE*3){ //FIXME nicer limit
 +            av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n");
 +            return;
 +        }
 +        for(x=0; x<w; x++){
 +            if(s->avctx->me_method == ME_ITER || !search)
 +                encode_q_branch2(s, 0, x, y);
 +            else
 +                encode_q_branch (s, 0, x, y);
 +        }
 +    }
 +}
 +
 +static void quantize(SnowContext *s, SubBand *b, IDWTELEM *dst, DWTELEM *src, int stride, int bias){
 +    const int w= b->width;
 +    const int h= b->height;
 +    const int qlog= av_clip(s->qlog + b->qlog, 0, QROOT*16);
 +    const int qmul= ff_qexp[qlog&(QROOT-1)]<<((qlog>>QSHIFT) + ENCODER_EXTRA_BITS);
 +    int x,y, thres1, thres2;
 +
 +    if(s->qlog == LOSSLESS_QLOG){
 +        for(y=0; y<h; y++)
 +            for(x=0; x<w; x++)
 +                dst[x + y*stride]= src[x + y*stride];
 +        return;
 +    }
 +
 +    bias= bias ? 0 : (3*qmul)>>3;
 +    thres1= ((qmul - bias)>>QEXPSHIFT) - 1;
 +    thres2= 2*thres1;
 +
 +    if(!bias){
 +        for(y=0; y<h; y++){
 +            for(x=0; x<w; x++){
 +                int i= src[x + y*stride];
 +
 +                if((unsigned)(i+thres1) > thres2){
 +                    if(i>=0){
 +                        i<<= QEXPSHIFT;
 +                        i/= qmul; //FIXME optimize
 +                        dst[x + y*stride]=  i;
 +                    }else{
 +                        i= -i;
 +                        i<<= QEXPSHIFT;
 +                        i/= qmul; //FIXME optimize
 +                        dst[x + y*stride]= -i;
 +                    }
 +                }else
 +                    dst[x + y*stride]= 0;
 +            }
 +        }
 +    }else{
 +        for(y=0; y<h; y++){
 +            for(x=0; x<w; x++){
 +                int i= src[x + y*stride];
 +
 +                if((unsigned)(i+thres1) > thres2){
 +                    if(i>=0){
 +                        i<<= QEXPSHIFT;
 +                        i= (i + bias) / qmul; //FIXME optimize
 +                        dst[x + y*stride]=  i;
 +                    }else{
 +                        i= -i;
 +                        i<<= QEXPSHIFT;
 +                        i= (i + bias) / qmul; //FIXME optimize
 +                        dst[x + y*stride]= -i;
 +                    }
 +                }else
 +                    dst[x + y*stride]= 0;
 +            }
 +        }
 +    }
 +}
 +
 +static void dequantize(SnowContext *s, SubBand *b, IDWTELEM *src, int stride){
 +    const int w= b->width;
 +    const int h= b->height;
 +    const int qlog= av_clip(s->qlog + b->qlog, 0, QROOT*16);
 +    const int qmul= ff_qexp[qlog&(QROOT-1)]<<(qlog>>QSHIFT);
 +    const int qadd= (s->qbias*qmul)>>QBIAS_SHIFT;
 +    int x,y;
 +
 +    if(s->qlog == LOSSLESS_QLOG) return;
 +
 +    for(y=0; y<h; y++){
 +        for(x=0; x<w; x++){
 +            int i= src[x + y*stride];
 +            if(i<0){
 +                src[x + y*stride]= -((-i*qmul + qadd)>>(QEXPSHIFT)); //FIXME try different bias
 +            }else if(i>0){
 +                src[x + y*stride]=  (( i*qmul + qadd)>>(QEXPSHIFT));
 +            }
 +        }
 +    }
 +}
 +
 +static void decorrelate(SnowContext *s, SubBand *b, IDWTELEM *src, int stride, int inverse, int use_median){
 +    const int w= b->width;
 +    const int h= b->height;
 +    int x,y;
 +
 +    for(y=h-1; y>=0; y--){
 +        for(x=w-1; x>=0; x--){
 +            int i= x + y*stride;
 +
 +            if(x){
 +                if(use_median){
 +                    if(y && x+1<w) src[i] -= mid_pred(src[i - 1], src[i - stride], src[i - stride + 1]);
 +                    else  src[i] -= src[i - 1];
 +                }else{
 +                    if(y) src[i] -= mid_pred(src[i - 1], src[i - stride], src[i - 1] + src[i - stride] - src[i - 1 - stride]);
 +                    else  src[i] -= src[i - 1];
 +                }
 +            }else{
 +                if(y) src[i] -= src[i - stride];
 +            }
 +        }
 +    }
 +}
 +
 +static void correlate(SnowContext *s, SubBand *b, IDWTELEM *src, int stride, int inverse, int use_median){
 +    const int w= b->width;
 +    const int h= b->height;
 +    int x,y;
 +
 +    for(y=0; y<h; y++){
 +        for(x=0; x<w; x++){
 +            int i= x + y*stride;
 +
 +            if(x){
 +                if(use_median){
 +                    if(y && x+1<w) src[i] += mid_pred(src[i - 1], src[i - stride], src[i - stride + 1]);
 +                    else  src[i] += src[i - 1];
 +                }else{
 +                    if(y) src[i] += mid_pred(src[i - 1], src[i - stride], src[i - 1] + src[i - stride] - src[i - 1 - stride]);
 +                    else  src[i] += src[i - 1];
 +                }
 +            }else{
 +                if(y) src[i] += src[i - stride];
 +            }
 +        }
 +    }
 +}
 +
 +static void encode_qlogs(SnowContext *s){
 +    int plane_index, level, orientation;
 +
 +    for(plane_index=0; plane_index<FFMIN(s->nb_planes, 2); plane_index++){
 +        for(level=0; level<s->spatial_decomposition_count; level++){
 +            for(orientation=level ? 1:0; orientation<4; orientation++){
 +                if(orientation==2) continue;
 +                put_symbol(&s->c, s->header_state, s->plane[plane_index].band[level][orientation].qlog, 1);
 +            }
 +        }
 +    }
 +}
 +
 +static void encode_header(SnowContext *s){
 +    int plane_index, i;
 +    uint8_t kstate[32];
 +
 +    memset(kstate, MID_STATE, sizeof(kstate));
 +
 +    put_rac(&s->c, kstate, s->keyframe);
 +    if(s->keyframe || s->always_reset){
 +        ff_snow_reset_contexts(s);
 +        s->last_spatial_decomposition_type=
 +        s->last_qlog=
 +        s->last_qbias=
 +        s->last_mv_scale=
 +        s->last_block_max_depth= 0;
 +        for(plane_index=0; plane_index<2; plane_index++){
 +            Plane *p= &s->plane[plane_index];
 +            p->last_htaps=0;
 +            p->last_diag_mc=0;
 +            memset(p->last_hcoeff, 0, sizeof(p->last_hcoeff));
 +        }
 +    }
 +    if(s->keyframe){
 +        put_symbol(&s->c, s->header_state, s->version, 0);
 +        put_rac(&s->c, s->header_state, s->always_reset);
 +        put_symbol(&s->c, s->header_state, s->temporal_decomposition_type, 0);
 +        put_symbol(&s->c, s->header_state, s->temporal_decomposition_count, 0);
 +        put_symbol(&s->c, s->header_state, s->spatial_decomposition_count, 0);
 +        put_symbol(&s->c, s->header_state, s->colorspace_type, 0);
 +        if (s->nb_planes > 2) {
 +            put_symbol(&s->c, s->header_state, s->chroma_h_shift, 0);
 +            put_symbol(&s->c, s->header_state, s->chroma_v_shift, 0);
 +        }
 +        put_rac(&s->c, s->header_state, s->spatial_scalability);
 +//        put_rac(&s->c, s->header_state, s->rate_scalability);
 +        put_symbol(&s->c, s->header_state, s->max_ref_frames-1, 0);
 +
 +        encode_qlogs(s);
 +    }
 +
 +    if(!s->keyframe){
 +        int update_mc=0;
 +        for(plane_index=0; plane_index<FFMIN(s->nb_planes, 2); plane_index++){
 +            Plane *p= &s->plane[plane_index];
 +            update_mc |= p->last_htaps   != p->htaps;
 +            update_mc |= p->last_diag_mc != p->diag_mc;
 +            update_mc |= !!memcmp(p->last_hcoeff, p->hcoeff, sizeof(p->hcoeff));
 +        }
 +        put_rac(&s->c, s->header_state, update_mc);
 +        if(update_mc){
 +            for(plane_index=0; plane_index<FFMIN(s->nb_planes, 2); plane_index++){
 +                Plane *p= &s->plane[plane_index];
 +                put_rac(&s->c, s->header_state, p->diag_mc);
 +                put_symbol(&s->c, s->header_state, p->htaps/2-1, 0);
 +                for(i= p->htaps/2; i; i--)
 +                    put_symbol(&s->c, s->header_state, FFABS(p->hcoeff[i]), 0);
 +            }
 +        }
 +        if(s->last_spatial_decomposition_count != s->spatial_decomposition_count){
 +            put_rac(&s->c, s->header_state, 1);
 +            put_symbol(&s->c, s->header_state, s->spatial_decomposition_count, 0);
 +            encode_qlogs(s);
 +        }else
 +            put_rac(&s->c, s->header_state, 0);
 +    }
 +
 +    put_symbol(&s->c, s->header_state, s->spatial_decomposition_type - s->last_spatial_decomposition_type, 1);
 +    put_symbol(&s->c, s->header_state, s->qlog            - s->last_qlog    , 1);
 +    put_symbol(&s->c, s->header_state, s->mv_scale        - s->last_mv_scale, 1);
 +    put_symbol(&s->c, s->header_state, s->qbias           - s->last_qbias   , 1);
 +    put_symbol(&s->c, s->header_state, s->block_max_depth - s->last_block_max_depth, 1);
 +
 +}
 +
 +static void update_last_header_values(SnowContext *s){
 +    int plane_index;
 +
 +    if(!s->keyframe){
 +        for(plane_index=0; plane_index<2; plane_index++){
 +            Plane *p= &s->plane[plane_index];
 +            p->last_diag_mc= p->diag_mc;
 +            p->last_htaps  = p->htaps;
 +            memcpy(p->last_hcoeff, p->hcoeff, sizeof(p->hcoeff));
 +        }
 +    }
 +
 +    s->last_spatial_decomposition_type  = s->spatial_decomposition_type;
 +    s->last_qlog                        = s->qlog;
 +    s->last_qbias                       = s->qbias;
 +    s->last_mv_scale                    = s->mv_scale;
 +    s->last_block_max_depth             = s->block_max_depth;
 +    s->last_spatial_decomposition_count = s->spatial_decomposition_count;
 +}
 +
 +static int qscale2qlog(int qscale){
 +    return rint(QROOT*log2(qscale / (float)FF_QP2LAMBDA))
 +           + 61*QROOT/8; ///< 64 > 60
 +}
 +
 +static int ratecontrol_1pass(SnowContext *s, AVFrame *pict)
 +{
 +    /* Estimate the frame's complexity as a sum of weighted dwt coefficients.
 +     * FIXME we know exact mv bits at this point,
 +     * but ratecontrol isn't set up to include them. */
 +    uint32_t coef_sum= 0;
 +    int level, orientation, delta_qlog;
 +
 +    for(level=0; level<s->spatial_decomposition_count; level++){
 +        for(orientation=level ? 1 : 0; orientation<4; orientation++){
 +            SubBand *b= &s->plane[0].band[level][orientation];
 +            IDWTELEM *buf= b->ibuf;
 +            const int w= b->width;
 +            const int h= b->height;
 +            const int stride= b->stride;
 +            const int qlog= av_clip(2*QROOT + b->qlog, 0, QROOT*16);
 +            const int qmul= ff_qexp[qlog&(QROOT-1)]<<(qlog>>QSHIFT);
 +            const int qdiv= (1<<16)/qmul;
 +            int x, y;
 +            //FIXME this is ugly
 +            for(y=0; y<h; y++)
 +                for(x=0; x<w; x++)
 +                    buf[x+y*stride]= b->buf[x+y*stride];
 +            if(orientation==0)
 +                decorrelate(s, b, buf, stride, 1, 0);
 +            for(y=0; y<h; y++)
 +                for(x=0; x<w; x++)
 +                    coef_sum+= abs(buf[x+y*stride]) * qdiv >> 16;
 +        }
 +    }
 +
 +    /* ugly, ratecontrol just takes a sqrt again */
 +    av_assert0(coef_sum < INT_MAX);
 +    coef_sum = (uint64_t)coef_sum * coef_sum >> 16;
 +
 +    if(pict->pict_type == AV_PICTURE_TYPE_I){
 +        s->m.current_picture.mb_var_sum= coef_sum;
 +        s->m.current_picture.mc_mb_var_sum= 0;
 +    }else{
 +        s->m.current_picture.mc_mb_var_sum= coef_sum;
 +        s->m.current_picture.mb_var_sum= 0;
 +    }
 +
 +    pict->quality= ff_rate_estimate_qscale(&s->m, 1);
 +    if (pict->quality < 0)
 +        return INT_MIN;
 +    s->lambda= pict->quality * 3/2;
 +    delta_qlog= qscale2qlog(pict->quality) - s->qlog;
 +    s->qlog+= delta_qlog;
 +    return delta_qlog;
 +}
 +
 +static void calculate_visual_weight(SnowContext *s, Plane *p){
 +    int width = p->width;
 +    int height= p->height;
 +    int level, orientation, x, y;
 +
 +    for(level=0; level<s->spatial_decomposition_count; level++){
 +        for(orientation=level ? 1 : 0; orientation<4; orientation++){
 +            SubBand *b= &p->band[level][orientation];
 +            IDWTELEM *ibuf= b->ibuf;
 +            int64_t error=0;
 +
 +            memset(s->spatial_idwt_buffer, 0, sizeof(*s->spatial_idwt_buffer)*width*height);
 +            ibuf[b->width/2 + b->height/2*b->stride]= 256*16;
 +            ff_spatial_idwt(s->spatial_idwt_buffer, s->temp_idwt_buffer, width, height, width, s->spatial_decomposition_type, s->spatial_decomposition_count);
 +            for(y=0; y<height; y++){
 +                for(x=0; x<width; x++){
 +          &