]> git.sesse.net Git - ffmpeg/commitdiff
Merge remote-tracking branch 'qatar/master'
authorMichael Niedermayer <michaelni@gmx.at>
Fri, 25 Nov 2011 00:38:21 +0000 (01:38 +0100)
committerMichael Niedermayer <michaelni@gmx.at>
Fri, 25 Nov 2011 03:34:44 +0000 (04:34 +0100)
* qatar/master:
  snow: split snow in snowdec and snowenc
  tiffenc: deprecate using compression_level
  swscale: fix failing fate tests.
  swscale: add support for planar RGB input.
  h264: add support for decoding planar RGB images.
  Clean up swscale pixfmt macros using av_pix_fmt_descriptors[].
  pixfmt: add planar RGB formats.

Conflicts:
libavcodec/h264.c
libavcodec/snow.c
libavcodec/utils.c
libavutil/avutil.h
libavutil/pixdesc.c
libavutil/pixfmt.h
libswscale/swscale.c
libswscale/swscale_internal.h
libswscale/swscale_unscaled.c
libswscale/utils.c

Merged-by: Michael Niedermayer <michaelni@gmx.at>
17 files changed:
1  2 
libavcodec/Makefile
libavcodec/h264.c
libavcodec/snow.c
libavcodec/snow.h
libavcodec/snowdec.c
libavcodec/snowenc.c
libavcodec/tiffenc.c
libavcodec/utils.c
libavcodec/version.h
libavutil/avutil.h
libavutil/pixdesc.c
libavutil/pixdesc.h
libavutil/pixfmt.h
libswscale/swscale.c
libswscale/swscale_internal.h
libswscale/swscale_unscaled.c
libswscale/utils.c

diff --combined libavcodec/Makefile
index 4f651412525e18d01c41a0c87b9d92ea93bc0d03,37aa8ee331e53f6988a6affbfa331491de586a43..07f7739738d4321c94330ed6bc2bfac546492724
@@@ -1,5 -1,3 +1,5 @@@
 +include $(SUBDIR)../config.mak
 +
  NAME = avcodec
  FFLIBS = avutil
  
@@@ -18,7 -16,6 +18,7 @@@ OBJS = allcodecs.
         options.o                                                        \
         parser.o                                                         \
         raw.o                                                            \
 +       rawdec.o                                                         \
         resample.o                                                       \
         resample2.o                                                      \
         simple_idct.o                                                    \
@@@ -27,7 -24,6 +27,7 @@@
  # parts needed for many different codecs
  OBJS-$(CONFIG_AANDCT)                  += aandcttab.o
  OBJS-$(CONFIG_AC3DSP)                  += ac3dsp.o
 +OBJS-$(CONFIG_CRYSTALHD)               += crystalhd.o
  OBJS-$(CONFIG_ENCODERS)                += faandct.o jfdctfst.o jfdctint.o
  OBJS-$(CONFIG_DCT)                     += dct.o dct32_fixed.o dct32_float.o
  OBJS-$(CONFIG_DWT)                     += dwt.o
@@@ -81,7 -77,7 +81,7 @@@ OBJS-$(CONFIG_AMV_DECODER)             
  OBJS-$(CONFIG_ANM_DECODER)             += anm.o
  OBJS-$(CONFIG_ANSI_DECODER)            += ansi.o cga_data.o
  OBJS-$(CONFIG_APE_DECODER)             += apedec.o
 -OBJS-$(CONFIG_ASS_DECODER)             += assdec.o ass.o
 +OBJS-$(CONFIG_ASS_DECODER)             += assdec.o ass.o ass_split.o
  OBJS-$(CONFIG_ASS_ENCODER)             += assenc.o ass.o
  OBJS-$(CONFIG_ASV1_DECODER)            += asv1.o mpeg12data.o
  OBJS-$(CONFIG_ASV1_ENCODER)            += asv1.o mpeg12data.o
@@@ -97,7 -93,6 +97,7 @@@ OBJS-$(CONFIG_BFI_DECODER)             
  OBJS-$(CONFIG_BINK_DECODER)            += bink.o binkdsp.o
  OBJS-$(CONFIG_BINKAUDIO_DCT_DECODER)   += binkaudio.o wma.o
  OBJS-$(CONFIG_BINKAUDIO_RDFT_DECODER)  += binkaudio.o wma.o
 +OBJS-$(CONFIG_BINTEXT_DECODER)         += bintext.o cga_data.o
  OBJS-$(CONFIG_BMP_DECODER)             += bmp.o msrledec.o
  OBJS-$(CONFIG_BMP_ENCODER)             += bmpenc.o
  OBJS-$(CONFIG_BMV_VIDEO_DECODER)       += bmv.o
@@@ -113,9 -108,6 +113,9 @@@ OBJS-$(CONFIG_COOK_DECODER)            
  OBJS-$(CONFIG_CSCD_DECODER)            += cscd.o
  OBJS-$(CONFIG_CYUV_DECODER)            += cyuv.o
  OBJS-$(CONFIG_DCA_DECODER)             += dca.o synth_filter.o dcadsp.o
 +OBJS-$(CONFIG_DCA_ENCODER)             += dcaenc.o
 +OBJS-$(CONFIG_DIRAC_DECODER)           += diracdec.o dirac.o diracdsp.o \
 +                                          dirac_arith.o mpeg12data.o dwt.o
  OBJS-$(CONFIG_DFA_DECODER)             += dfa.o
  OBJS-$(CONFIG_DNXHD_DECODER)           += dnxhddec.o dnxhddata.o
  OBJS-$(CONFIG_DNXHD_ENCODER)           += dnxhdenc.o dnxhddata.o       \
@@@ -148,26 -140,20 +148,26 @@@ OBJS-$(CONFIG_EATQI_DECODER)           
  OBJS-$(CONFIG_EIGHTBPS_DECODER)        += 8bps.o
  OBJS-$(CONFIG_EIGHTSVX_EXP_DECODER)    += 8svx.o
  OBJS-$(CONFIG_EIGHTSVX_FIB_DECODER)    += 8svx.o
 +OBJS-$(CONFIG_EIGHTSVX_RAW_DECODER)    += 8svx.o
  OBJS-$(CONFIG_ESCAPE124_DECODER)       += escape124.o
  OBJS-$(CONFIG_FFV1_DECODER)            += ffv1.o rangecoder.o
  OBJS-$(CONFIG_FFV1_ENCODER)            += ffv1.o rangecoder.o
  OBJS-$(CONFIG_FFVHUFF_DECODER)         += huffyuv.o
  OBJS-$(CONFIG_FFVHUFF_ENCODER)         += huffyuv.o
 -OBJS-$(CONFIG_FLAC_DECODER)            += flacdec.o flacdata.o flac.o
 -OBJS-$(CONFIG_FLAC_ENCODER)            += flacenc.o flacdata.o flac.o
 +OBJS-$(CONFIG_FLAC_DECODER)            += flacdec.o flacdata.o flac.o vorbis_data.o
 +OBJS-$(CONFIG_FLAC_ENCODER)            += flacenc.o flacdata.o flac.o vorbis_data.o
  OBJS-$(CONFIG_FLASHSV_DECODER)         += flashsv.o
  OBJS-$(CONFIG_FLASHSV_ENCODER)         += flashsvenc.o
 +OBJS-$(CONFIG_FLASHSV2_ENCODER)        += flashsv2enc.o
  OBJS-$(CONFIG_FLASHSV2_DECODER)        += flashsv.o
  OBJS-$(CONFIG_FLIC_DECODER)            += flicvideo.o
  OBJS-$(CONFIG_FOURXM_DECODER)          += 4xm.o
  OBJS-$(CONFIG_FRAPS_DECODER)           += fraps.o
  OBJS-$(CONFIG_FRWU_DECODER)            += frwu.o
 +OBJS-$(CONFIG_G723_1_DECODER)          += g723_1.o acelp_vectors.o \
 +                                          celp_filters.o celp_math.o
 +OBJS-$(CONFIG_G723_1_ENCODER)          += g723_1.o
 +OBJS-$(CONFIG_G729_DECODER)            += g729dec.o lsp.o celp_math.o acelp_filters.o acelp_pitch_delay.o acelp_vectors.o g729postfilter.o
  OBJS-$(CONFIG_GIF_DECODER)             += gifdec.o lzw.o
  OBJS-$(CONFIG_GIF_ENCODER)             += gif.o lzwenc.o
  OBJS-$(CONFIG_GSM_DECODER)             += gsmdec.o gsmdec_data.o msgsmdec.o
@@@ -199,7 -185,6 +199,7 @@@ OBJS-$(CONFIG_H264_VDA_HWACCEL)        
  OBJS-$(CONFIG_HUFFYUV_DECODER)         += huffyuv.o
  OBJS-$(CONFIG_HUFFYUV_ENCODER)         += huffyuv.o
  OBJS-$(CONFIG_IDCIN_DECODER)           += idcinvideo.o
 +OBJS-$(CONFIG_IDF_DECODER)             += bintext.o cga_data.o
  OBJS-$(CONFIG_IFF_BYTERUN1_DECODER)    += iff.o
  OBJS-$(CONFIG_IFF_ILBM_DECODER)        += iff.o
  OBJS-$(CONFIG_IMC_DECODER)             += imc.o
@@@ -208,8 -193,6 +208,8 @@@ OBJS-$(CONFIG_INDEO3_DECODER)          
  OBJS-$(CONFIG_INDEO5_DECODER)          += indeo5.o ivi_common.o ivi_dsp.o
  OBJS-$(CONFIG_INTERPLAY_DPCM_DECODER)  += dpcm.o
  OBJS-$(CONFIG_INTERPLAY_VIDEO_DECODER) += interplayvideo.o
 +OBJS-$(CONFIG_JPEG2000_DECODER)        += j2kdec.o mqcdec.o mqc.o j2k.o j2k_dwt.o
 +OBJS-$(CONFIG_JPEG2000_ENCODER)        += j2kenc.o mqcenc.o mqc.o j2k.o j2k_dwt.o
  OBJS-$(CONFIG_JPEGLS_DECODER)          += jpeglsdec.o jpegls.o \
                                            mjpegdec.o mjpeg.o
  OBJS-$(CONFIG_JPEGLS_ENCODER)          += jpeglsenc.o jpegls.o
@@@ -266,13 -249,10 +266,13 @@@ OBJS-$(CONFIG_MPC7_DECODER)            
  OBJS-$(CONFIG_MPC8_DECODER)            += mpc8.o mpc.o mpegaudiodec.o      \
                                            mpegaudiodecheader.o mpegaudio.o \
                                            mpegaudiodata.o
 +OBJS-$(CONFIG_MPEGVIDEO_DECODER)       += mpeg12.o mpeg12data.o \
 +                                          mpegvideo.o error_resilience.o
  OBJS-$(CONFIG_MPEG_XVMC_DECODER)       += mpegvideo_xvmc.o
  OBJS-$(CONFIG_MPEG1VIDEO_DECODER)      += mpeg12.o mpeg12data.o \
                                            mpegvideo.o error_resilience.o
  OBJS-$(CONFIG_MPEG1VIDEO_ENCODER)      += mpeg12enc.o mpegvideo_enc.o \
 +                                          timecode.o                  \
                                            motion_est.o ratecontrol.o  \
                                            mpeg12.o mpeg12data.o       \
                                            mpegvideo.o error_resilience.o
@@@ -281,7 -261,6 +281,7 @@@ OBJS-$(CONFIG_MPEG2_VAAPI_HWACCEL)     
  OBJS-$(CONFIG_MPEG2VIDEO_DECODER)      += mpeg12.o mpeg12data.o \
                                            mpegvideo.o error_resilience.o
  OBJS-$(CONFIG_MPEG2VIDEO_ENCODER)      += mpeg12enc.o mpegvideo_enc.o \
 +                                          timecode.o                  \
                                            motion_est.o ratecontrol.o  \
                                            mpeg12.o mpeg12data.o       \
                                            mpegvideo.o error_resilience.o
@@@ -297,7 -276,6 +297,7 @@@ OBJS-$(CONFIG_MSMPEG4V3_ENCODER)       
                                            h263.o ituh263dec.o mpeg4videodec.o
  OBJS-$(CONFIG_MSRLE_DECODER)           += msrle.o msrledec.o
  OBJS-$(CONFIG_MSVIDEO1_DECODER)        += msvideo1.o
 +OBJS-$(CONFIG_MSVIDEO1_ENCODER)        += msvideo1enc.o elbg.o
  OBJS-$(CONFIG_MSZH_DECODER)            += lcldec.o
  OBJS-$(CONFIG_MXPEG_DECODER)           += mxpegdec.o mjpegdec.o mjpeg.o
  OBJS-$(CONFIG_NELLYMOSER_DECODER)      += nellymoserdec.o nellymoser.o
@@@ -319,9 -297,7 +319,9 @@@ OBJS-$(CONFIG_PNG_DECODER)             
  OBJS-$(CONFIG_PNG_ENCODER)             += png.o pngenc.o
  OBJS-$(CONFIG_PPM_DECODER)             += pnmdec.o pnm.o
  OBJS-$(CONFIG_PPM_ENCODER)             += pnmenc.o pnm.o
 -OBJS-$(CONFIG_PRORES_DECODER)          += proresdec.o proresdsp.o
 +OBJS-$(CONFIG_PRORES_DECODER)          += proresdec2.o
 +OBJS-$(CONFIG_PRORES_LGPL_DECODER)     += proresdec_lgpl.o proresdsp.o
 +OBJS-$(CONFIG_PRORES_ENCODER)          += proresenc.o
  OBJS-$(CONFIG_PTX_DECODER)             += ptx.o
  OBJS-$(CONFIG_QCELP_DECODER)           += qcelpdec.o celp_math.o         \
                                            celp_filters.o acelp_vectors.o \
@@@ -365,19 -341,15 +365,19 @@@ OBJS-$(CONFIG_SIPR_DECODER)            
  OBJS-$(CONFIG_SMACKAUD_DECODER)        += smacker.o
  OBJS-$(CONFIG_SMACKER_DECODER)         += smacker.o
  OBJS-$(CONFIG_SMC_DECODER)             += smc.o
- OBJS-$(CONFIG_SNOW_DECODER)            += snow.o rangecoder.o
- OBJS-$(CONFIG_SNOW_ENCODER)            += snow.o rangecoder.o motion_est.o \
-                                           ratecontrol.o h263.o             \
-                                           mpegvideo.o error_resilience.o   \
-                                           ituh263enc.o mpegvideo_enc.o     \
-                                           mpeg12data.o
+ OBJS-$(CONFIG_SNOW_DECODER)            += snowdec.o snow.o rangecoder.o
+ OBJS-$(CONFIG_SNOW_ENCODER)            += snowenc.o snow.o rangecoder.o    \
+                                           motion_est.o ratecontrol.o       \
+                                           h263.o mpegvideo.o               \
+                                           error_resilience.o ituh263enc.o  \
+                                           mpegvideo_enc.o mpeg12data.o
  OBJS-$(CONFIG_SOL_DPCM_DECODER)        += dpcm.o
 +OBJS-$(CONFIG_SONIC_DECODER)           += sonic.o
 +OBJS-$(CONFIG_SONIC_ENCODER)           += sonic.o
 +OBJS-$(CONFIG_SONIC_LS_ENCODER)        += sonic.o
  OBJS-$(CONFIG_SP5X_DECODER)            += sp5xdec.o mjpegdec.o mjpeg.o
  OBJS-$(CONFIG_SRT_DECODER)             += srtdec.o ass.o
 +OBJS-$(CONFIG_SRT_ENCODER)             += srtenc.o ass_split.o
  OBJS-$(CONFIG_SUNRAST_DECODER)         += sunrast.o
  OBJS-$(CONFIG_SVQ1_DECODER)            += svq1dec.o svq1.o h263.o \
                                            mpegvideo.o error_resilience.o
@@@ -436,7 -408,6 +436,7 @@@ OBJS-$(CONFIG_VP6_DECODER)             
  OBJS-$(CONFIG_VP8_DECODER)             += vp8.o vp8dsp.o vp56rac.o
  OBJS-$(CONFIG_VQA_DECODER)             += vqavideo.o
  OBJS-$(CONFIG_WAVPACK_DECODER)         += wavpack.o
 +OBJS-$(CONFIG_WMALOSSLESS_DECODER)     += wmalosslessdec.o wma.o
  OBJS-$(CONFIG_WMAPRO_DECODER)          += wmaprodec.o wma.o
  OBJS-$(CONFIG_WMAV1_DECODER)           += wmadec.o wma.o aactab.o
  OBJS-$(CONFIG_WMAV1_ENCODER)           += wmaenc.o wma.o aactab.o
@@@ -457,7 -428,6 +457,7 @@@ OBJS-$(CONFIG_WS_SND1_DECODER)         
  OBJS-$(CONFIG_XAN_DPCM_DECODER)        += dpcm.o
  OBJS-$(CONFIG_XAN_WC3_DECODER)         += xan.o
  OBJS-$(CONFIG_XAN_WC4_DECODER)         += xxan.o
 +OBJS-$(CONFIG_XBIN_DECODER)            += bintext.o cga_data.o
  OBJS-$(CONFIG_XL_DECODER)              += xl.o
  OBJS-$(CONFIG_XSUB_DECODER)            += xsubdec.o
  OBJS-$(CONFIG_XSUB_ENCODER)            += xsubenc.o
@@@ -560,40 -530,36 +560,40 @@@ OBJS-$(CONFIG_ADPCM_YAMAHA_ENCODER
  OBJS-$(CONFIG_ADTS_MUXER)              += mpeg4audio.o
  OBJS-$(CONFIG_CAF_DEMUXER)             += mpeg4audio.o mpegaudiodata.o
  OBJS-$(CONFIG_DV_DEMUXER)              += dvdata.o
 -OBJS-$(CONFIG_DV_MUXER)                += dvdata.o
 -OBJS-$(CONFIG_FLAC_DEMUXER)            += flacdec.o flacdata.o flac.o
 -OBJS-$(CONFIG_FLAC_MUXER)              += flacdec.o flacdata.o flac.o
 +OBJS-$(CONFIG_DV_MUXER)                += dvdata.o timecode.o
 +OBJS-$(CONFIG_FLAC_DEMUXER)            += flacdec.o flacdata.o flac.o vorbis_data.o
 +OBJS-$(CONFIG_FLAC_MUXER)              += flacdec.o flacdata.o flac.o vorbis_data.o
  OBJS-$(CONFIG_FLV_DEMUXER)             += mpeg4audio.o
  OBJS-$(CONFIG_GXF_DEMUXER)             += mpeg12data.o
  OBJS-$(CONFIG_IFF_DEMUXER)             += iff.o
  OBJS-$(CONFIG_LATM_MUXER)              += mpeg4audio.o
 -OBJS-$(CONFIG_MATROSKA_AUDIO_MUXER)    += xiph.o mpeg4audio.o \
 +OBJS-$(CONFIG_MATROSKA_AUDIO_MUXER)    += xiph.o mpeg4audio.o vorbis_data.o \
                                            flacdec.o flacdata.o flac.o
  OBJS-$(CONFIG_MATROSKA_DEMUXER)        += mpeg4audio.o mpegaudiodata.o
  OBJS-$(CONFIG_MATROSKA_MUXER)          += xiph.o mpeg4audio.o \
                                            flacdec.o flacdata.o flac.o \
 -                                          mpegaudiodata.o
 +                                          mpegaudiodata.o vorbis_data.o
  OBJS-$(CONFIG_MP3_MUXER)               += mpegaudiodata.o mpegaudiodecheader.o
  OBJS-$(CONFIG_MOV_DEMUXER)             += mpeg4audio.o mpegaudiodata.o
  OBJS-$(CONFIG_MOV_MUXER)               += mpeg4audio.o mpegaudiodata.o
  OBJS-$(CONFIG_MPEGTS_MUXER)            += mpegvideo.o mpeg4audio.o
  OBJS-$(CONFIG_MPEGTS_DEMUXER)          += mpeg4audio.o mpegaudiodata.o
 +OBJS-$(CONFIG_MXF_MUXER)               += timecode.o
  OBJS-$(CONFIG_NUT_MUXER)               += mpegaudiodata.o
  OBJS-$(CONFIG_OGG_DEMUXER)             += flacdec.o flacdata.o flac.o \
 -                                          dirac.o mpeg12data.o
 -OBJS-$(CONFIG_OGG_MUXER)               += xiph.o flacdec.o flacdata.o flac.o
 +                                          dirac.o mpeg12data.o vorbis_data.o
 +OBJS-$(CONFIG_OGG_MUXER)               += xiph.o flacdec.o flacdata.o flac.o \
 +                                          vorbis_data.o
  OBJS-$(CONFIG_RTP_MUXER)               += mpeg4audio.o mpegvideo.o xiph.o
  OBJS-$(CONFIG_SPDIF_DEMUXER)           += aacadtsdec.o mpeg4audio.o
  OBJS-$(CONFIG_WEBM_MUXER)              += xiph.o mpeg4audio.o \
                                            flacdec.o flacdata.o flac.o \
 -                                          mpegaudiodata.o
 +                                          mpegaudiodata.o vorbis_data.o
  OBJS-$(CONFIG_WTV_DEMUXER)             += mpeg4audio.o mpegaudiodata.o
  
  # external codec libraries
 +OBJS-$(CONFIG_LIBAACPLUS_ENCODER)         += libaacplus.o
 +OBJS-$(CONFIG_LIBCELT_DECODER)            += libcelt_dec.o
  OBJS-$(CONFIG_LIBDIRAC_DECODER)           += libdiracdec.o
  OBJS-$(CONFIG_LIBDIRAC_ENCODER)           += libdiracenc.o libdirac_libschro.o
  OBJS-$(CONFIG_LIBFAAC_ENCODER)            += libfaac.o
@@@ -605,8 -571,7 +605,8 @@@ OBJS-$(CONFIG_LIBMP3LAME_ENCODER
  OBJS-$(CONFIG_LIBOPENCORE_AMRNB_DECODER)  += libopencore-amr.o
  OBJS-$(CONFIG_LIBOPENCORE_AMRNB_ENCODER)  += libopencore-amr.o
  OBJS-$(CONFIG_LIBOPENCORE_AMRWB_DECODER)  += libopencore-amr.o
 -OBJS-$(CONFIG_LIBOPENJPEG_DECODER)        += libopenjpeg.o
 +OBJS-$(CONFIG_LIBOPENJPEG_DECODER)        += libopenjpegdec.o
 +OBJS-$(CONFIG_LIBOPENJPEG_ENCODER)        += libopenjpegenc.o
  OBJS-$(CONFIG_LIBSCHROEDINGER_DECODER)    += libschroedingerdec.o \
                                               libschroedinger.o    \
                                               libdirac_libschro.o
@@@ -615,9 -580,7 +615,9 @@@ OBJS-$(CONFIG_LIBSCHROEDINGER_ENCODER
                                               libdirac_libschro.o
  OBJS-$(CONFIG_LIBSPEEX_DECODER)           += libspeexdec.o
  OBJS-$(CONFIG_LIBSPEEX_ENCODER)           += libspeexenc.o
 +OBJS-$(CONFIG_LIBSTAGEFRIGHT_H264_DECODER)+= libstagefright.o
  OBJS-$(CONFIG_LIBTHEORA_ENCODER)          += libtheoraenc.o
 +OBJS-$(CONFIG_LIBUTVIDEO_DECODER)         += libutvideo.o
  OBJS-$(CONFIG_LIBVO_AACENC_ENCODER)       += libvo-aacenc.o mpeg4audio.o
  OBJS-$(CONFIG_LIBVO_AMRWBENC_ENCODER)     += libvo-amrwbenc.o
  OBJS-$(CONFIG_LIBVORBIS_ENCODER)          += libvorbis.o vorbis_data.o
@@@ -638,8 -601,7 +638,8 @@@ OBJS-$(CONFIG_DIRAC_PARSER)            
  OBJS-$(CONFIG_DNXHD_PARSER)            += dnxhd_parser.o
  OBJS-$(CONFIG_DVBSUB_PARSER)           += dvbsub_parser.o
  OBJS-$(CONFIG_DVDSUB_PARSER)           += dvdsub_parser.o
 -OBJS-$(CONFIG_FLAC_PARSER)             += flac_parser.o flacdata.o flac.o
 +OBJS-$(CONFIG_FLAC_PARSER)             += flac_parser.o flacdata.o flac.o \
 +                                          vorbis_data.o
  OBJS-$(CONFIG_H261_PARSER)             += h261_parser.o
  OBJS-$(CONFIG_H263_PARSER)             += h263_parser.o
  OBJS-$(CONFIG_H264_PARSER)             += h264_parser.o h264.o            \
@@@ -689,7 -651,6 +689,7 @@@ OBJS-$(CONFIG_TEXT2MOVSUB_BSF
  # thread libraries
  OBJS-$(HAVE_PTHREADS)                  += pthread.o
  OBJS-$(HAVE_W32THREADS)                += pthread.o
 +OBJS-$(HAVE_OS2THREADS)                += pthread.o
  
  OBJS-$(CONFIG_MLIB)                    += mlib/dsputil_mlib.o           \
  
@@@ -711,12 -672,14 +711,12 @@@ SKIPHEADERS-$(CONFIG_DXVA2)            
  SKIPHEADERS-$(CONFIG_LIBDIRAC)         += libdirac.h
  SKIPHEADERS-$(CONFIG_LIBSCHROEDINGER)  += libschroedinger.h
  SKIPHEADERS-$(CONFIG_VAAPI)            += vaapi_internal.h
 -SKIPHEADERS-$(CONFIG_VDA)              += vda.h vda_internal.h
 +SKIPHEADERS-$(CONFIG_VDA)              += vda_internal.h
  SKIPHEADERS-$(CONFIG_VDPAU)            += vdpau.h
  SKIPHEADERS-$(CONFIG_XVMC)             += xvmc.h
  SKIPHEADERS-$(HAVE_W32THREADS)         += w32pthreads.h
  
- TESTPROGS = cabac dct fft fft-fixed h264 iirfilter rangecoder snow
 -EXAMPLES = api
 -
 -TESTPROGS = cabac dct fft fft-fixed h264 iirfilter rangecoder
++TESTPROGS = cabac dct fft fft-fixed h264 iirfilter rangecoder snowenc
  TESTPROGS-$(HAVE_MMX) += motion
  TESTOBJS = dctref.o
  
@@@ -764,10 -727,3 +764,10 @@@ $(SUBDIR)motionpixels.o: $(SUBDIR)motio
  $(SUBDIR)pcm.o: $(SUBDIR)pcm_tables.h
  $(SUBDIR)qdm2.o: $(SUBDIR)qdm2_tables.h
  endif
 +
 +CODEC_NAMES_SH := $(SRC_PATH)/$(SUBDIR)codec_names.sh
 +AVCODEC_H      := $(SRC_PATH)/$(SUBDIR)avcodec.h
 +$(SUBDIR)codec_names.h: $(CODEC_NAMES_SH) config.h $(AVCODEC_H)
 +      $(CC) $(CPPFLAGS) $(CFLAGS) -E $(AVCODEC_H) | \
 +      $(CODEC_NAMES_SH) config.h $@
 +$(SUBDIR)utils.o: $(SUBDIR)codec_names.h
diff --combined libavcodec/h264.c
index 893b3d385da7bfa9c542dc282e266e51fa2d4f99,ad1ab69e29b1be97723dd2448e1f77f67a7f3f66..a08573e221627266abcb275612d8fa125052ae89
@@@ -2,20 -2,20 +2,20 @@@
   * H.26L/H.264/AVC/JVT/14496-10/... decoder
   * Copyright (c) 2003 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.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * FFmpeg is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
 - * License along with Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
@@@ -26,7 -26,6 +26,7 @@@
   */
  
  #include "libavutil/imgutils.h"
 +#include "libavutil/opt.h"
  #include "internal.h"
  #include "dsputil.h"
  #include "avcodec.h"
@@@ -99,9 -98,12 +99,9 @@@ int ff_h264_check_intra4x4_pred_mode(H2
      }
  
      return 0;
 -} //FIXME cleanup like ff_h264_check_intra_pred_mode
 +} //FIXME cleanup like check_intra_pred_mode
  
 -/**
 - * checks if the top & left blocks are available if needed & changes the dc mode so it only uses the available blocks.
 - */
 -int ff_h264_check_intra_pred_mode(H264Context *h, int mode){
 +static int check_intra_pred_mode(H264Context *h, int mode, int is_chroma){
      MpegEncContext * const s = &h->s;
      static const int8_t top [7]= {LEFT_DC_PRED8x8, 1,-1,-1};
      static const int8_t left[7]= { TOP_DC_PRED8x8,-1, 2,-1,DC_128_PRED8x8};
  
      if((h->left_samples_available&0x8080) != 0x8080){
          mode= left[ mode ];
 -        if(h->left_samples_available&0x8080){ //mad cow disease mode, aka MBAFF + constrained_intra_pred
 +        if(is_chroma && (h->left_samples_available&0x8080)){ //mad cow disease mode, aka MBAFF + constrained_intra_pred
              mode= ALZHEIMER_DC_L0T_PRED8x8 + (!(h->left_samples_available&0x8000)) + 2*(mode == DC_128_PRED8x8);
          }
          if(mode<0){
      return mode;
  }
  
 +/**
 + * checks if the top & left blocks are available if needed & changes the dc mode so it only uses the available blocks.
 + */
 +int ff_h264_check_intra16x16_pred_mode(H264Context *h, int mode)
 +{
 +    return check_intra_pred_mode(h, mode, 0);
 +}
 +
 +/**
 + * checks if the top & left blocks are available if needed & changes the dc mode so it only uses the available blocks.
 + */
 +int ff_h264_check_intra_chroma_pred_mode(H264Context *h, int mode)
 +{
 +    return check_intra_pred_mode(h, mode, 1);
 +}
 +
 +
  const uint8_t *ff_h264_decode_nal(H264Context *h, const uint8_t *src, int *dst_length, int *consumed, int length){
      int i, si, di;
      uint8_t *dst;
          i-= RS;
      }
  
 -    if(i>=length-1){ //no escaped 0
 -        *dst_length= length;
 -        *consumed= length+1; //+1 for the header
 -        return src;
 -    }
 -
      bufidx = h->nal_unit_type == NAL_DPC ? 1 : 0; // use second escape buffer for inter data
 -    av_fast_malloc(&h->rbsp_buffer[bufidx], &h->rbsp_buffer_size[bufidx], length+FF_INPUT_BUFFER_PADDING_SIZE);
 +    si=h->rbsp_buffer_size[bufidx];
 +    av_fast_malloc(&h->rbsp_buffer[bufidx], &h->rbsp_buffer_size[bufidx], length+FF_INPUT_BUFFER_PADDING_SIZE+MAX_MBPAIR_SIZE);
      dst= h->rbsp_buffer[bufidx];
 +    if(si != h->rbsp_buffer_size[bufidx])
 +        memset(dst + length, 0, FF_INPUT_BUFFER_PADDING_SIZE+MAX_MBPAIR_SIZE);
  
      if (dst == NULL){
          return NULL;
      }
  
 +    if(i>=length-1){ //no escaped 0
 +        *dst_length= length;
 +        *consumed= length+1; //+1 for the header
 +        if(h->s.avctx->flags2 & CODEC_FLAG2_FAST){
 +            return src;
 +        }else{
 +            memcpy(dst, src, length);
 +            return dst;
 +        }
 +    }
 +
  //printf("decoding esc\n");
      memcpy(dst, src, i);
      si=di=i;
@@@ -730,7 -707,7 +730,7 @@@ prefetch_motion(H264Context *h, int lis
              s->dsp.prefetch(src[1]+off, s->linesize, 4);
              s->dsp.prefetch(src[2]+off, s->linesize, 4);
          }else{
 -            off= ((mx>>1) << pixel_shift) + ((my>>1) + (s->mb_x&7))*s->uvlinesize + (64 << pixel_shift);
 +            off= (((mx>>1)+64)<<pixel_shift) + ((my>>1) + (s->mb_x&7))*s->uvlinesize;
              s->dsp.prefetch(src[1]+off, src[2]-src[1], 2);
          }
      }
@@@ -1052,38 -1029,29 +1052,38 @@@ static av_cold void common_init(H264Con
      s->height = s->avctx->height;
      s->codec_id= s->avctx->codec->id;
  
 -    ff_h264dsp_init(&h->h264dsp, 8, 1);
 -    ff_h264_pred_init(&h->hpc, s->codec_id, 8, 1);
 +    s->avctx->bits_per_raw_sample = 8;
 +    h->cur_chroma_format_idc = 1;
 +
 +    ff_h264dsp_init(&h->h264dsp,
 +                    s->avctx->bits_per_raw_sample, h->cur_chroma_format_idc);
 +    ff_h264_pred_init(&h->hpc, s->codec_id,
 +                      s->avctx->bits_per_raw_sample, h->cur_chroma_format_idc);
  
      h->dequant_coeff_pps= -1;
      s->unrestricted_mv=1;
  
 +    s->dsp.dct_bits = 16;
      dsputil_init(&s->dsp, s->avctx); // needed so that idct permutation is known early
  
      memset(h->pps.scaling_matrix4, 16, 6*16*sizeof(uint8_t));
      memset(h->pps.scaling_matrix8, 16, 2*64*sizeof(uint8_t));
  }
  
 -int ff_h264_decode_extradata(H264Context *h)
 +int ff_h264_decode_extradata(H264Context *h, const uint8_t *buf, int size)
  {
      AVCodecContext *avctx = h->s.avctx;
  
 -    if(avctx->extradata[0] == 1){
 +    if(!buf || size <= 0)
 +        return -1;
 +
 +    if(buf[0] == 1){
          int i, cnt, nalsize;
 -        unsigned char *p = avctx->extradata;
 +        const unsigned char *p = buf;
  
          h->is_avc = 1;
  
 -        if(avctx->extradata_size < 7) {
 +        if(size < 7) {
              av_log(avctx, AV_LOG_ERROR, "avcC too short\n");
              return -1;
          }
          p += 6;
          for (i = 0; i < cnt; i++) {
              nalsize = AV_RB16(p) + 2;
 -            if (p - avctx->extradata + nalsize > avctx->extradata_size)
 +            if(nalsize > size - (p-buf))
                  return -1;
              if(decode_nal_units(h, p, nalsize) < 0) {
                  av_log(avctx, AV_LOG_ERROR, "Decoding sps %d from avcC failed\n", i);
          cnt = *(p++); // Number of pps
          for (i = 0; i < cnt; i++) {
              nalsize = AV_RB16(p) + 2;
 -            if (p - avctx->extradata + nalsize > avctx->extradata_size)
 +            if(nalsize > size - (p-buf))
                  return -1;
              if (decode_nal_units(h, p, nalsize) < 0) {
                  av_log(avctx, AV_LOG_ERROR, "Decoding pps %d from avcC failed\n", i);
              p += nalsize;
          }
          // Now store right nal length size, that will be use to parse all other nals
 -        h->nal_length_size = (avctx->extradata[4] & 0x03) + 1;
 +        h->nal_length_size = (buf[4] & 0x03) + 1;
      } else {
          h->is_avc = 0;
 -        if(decode_nal_units(h, avctx->extradata, avctx->extradata_size) < 0)
 +        if(decode_nal_units(h, buf, size) < 0)
              return -1;
      }
      return 0;
@@@ -1166,7 -1134,7 +1166,7 @@@ av_cold int ff_h264_decode_init(AVCodec
      }
  
      if(avctx->extradata_size > 0 && avctx->extradata &&
 -        ff_h264_decode_extradata(h))
 +        ff_h264_decode_extradata(h, avctx->extradata, avctx->extradata_size))
          return -1;
  
      if(h->sps.bitstream_restriction_flag && s->avctx->has_b_frames < h->sps.num_reorder_frames){
@@@ -1291,7 -1259,6 +1291,7 @@@ static int decode_update_thread_context
      copy_picture_range(h->delayed_pic, h1->delayed_pic, MAX_DELAYED_PIC_COUNT+2, s, s1);
  
      h->last_slice_type = h1->last_slice_type;
 +    h->sync            = h1->sync;
  
      if(!s->current_picture_ptr) return 0;
  
@@@ -1475,29 -1442,10 +1475,29 @@@ static void decode_postinit(H264Contex
          s->low_delay= 0;
      }
  
 +    for (i = 0; 1; i++) {
 +        if(i == MAX_DELAYED_PIC_COUNT || cur->poc < h->last_pocs[i]){
 +            if(i)
 +                h->last_pocs[i-1] = cur->poc;
 +            break;
 +        } else if(i) {
 +            h->last_pocs[i-1]= h->last_pocs[i];
 +        }
 +    }
 +    out_of_order = MAX_DELAYED_PIC_COUNT - i;
 +    if(   cur->f.pict_type == AV_PICTURE_TYPE_B
 +       || (h->last_pocs[MAX_DELAYED_PIC_COUNT-2] > INT_MIN && h->last_pocs[MAX_DELAYED_PIC_COUNT-1] - h->last_pocs[MAX_DELAYED_PIC_COUNT-2] > 2))
 +        out_of_order = FFMAX(out_of_order, 1);
 +    if(s->avctx->has_b_frames < out_of_order && !h->sps.bitstream_restriction_flag){
 +        av_log(s->avctx, AV_LOG_WARNING, "Increasing reorder buffer to %d\n", out_of_order);
 +        s->avctx->has_b_frames = out_of_order;
 +        s->low_delay = 0;
 +    }
 +
      pics = 0;
      while(h->delayed_pic[pics]) pics++;
  
 -    assert(pics <= MAX_DELAYED_PIC_COUNT);
 +    av_assert0(pics <= MAX_DELAYED_PIC_COUNT);
  
      h->delayed_pic[pics++] = cur;
      if (cur->f.reference == 0)
          h->next_outputed_poc= INT_MIN;
      out_of_order = out->poc < h->next_outputed_poc;
  
 -    if(h->sps.bitstream_restriction_flag && s->avctx->has_b_frames >= h->sps.num_reorder_frames)
 -        { }
 -    else if (out_of_order && pics-1 == s->avctx->has_b_frames &&
 -             s->avctx->has_b_frames < MAX_DELAYED_PIC_COUNT) {
 -        int cnt = 0, invalid = 0;
 -        for (i = 0; i < MAX_DELAYED_PIC_COUNT; i++) {
 -            cnt += out->poc < h->last_pocs[i];
 -            invalid += h->last_pocs[i] == INT_MIN;
 -        }
 -        if (invalid + cnt < MAX_DELAYED_PIC_COUNT) {
 -            s->avctx->has_b_frames = FFMAX(s->avctx->has_b_frames, cnt);
 -        } else if (cnt) {
 -            for (i = 0; i < MAX_DELAYED_PIC_COUNT; i++)
 -                h->last_pocs[i] = INT_MIN;
 -        }
 -        s->low_delay = 0;
 -    } else if (s->low_delay &&
 -               ((h->next_outputed_poc != INT_MIN && out->poc > h->next_outputed_poc + 2) ||
 -                cur->f.pict_type == AV_PICTURE_TYPE_B)) {
 -        s->low_delay = 0;
 -        s->avctx->has_b_frames++;
 -    }
 -
      if(out_of_order || pics > s->avctx->has_b_frames){
          out->f.reference &= ~DELAYED_PIC_REF;
          out->owner2 = s; // for frame threading, the owner must be the second field's thread
          for(i=out_idx; h->delayed_pic[i]; i++)
              h->delayed_pic[i] = h->delayed_pic[i+1];
      }
 -    memmove(h->last_pocs, &h->last_pocs[1], sizeof(*h->last_pocs) * (MAX_DELAYED_PIC_COUNT - 1));
 -    h->last_pocs[MAX_DELAYED_PIC_COUNT - 1] = out->poc;
      if(!out_of_order && pics > s->avctx->has_b_frames){
          h->next_output_pic = out;
          if (out_idx == 0 && h->delayed_pic[0] && (h->delayed_pic[0]->f.key_frame || h->delayed_pic[0]->mmco_reset)) {
          av_log(s->avctx, AV_LOG_DEBUG, "no picture\n");
      }
  
 +    if (h->next_output_pic && h->next_output_pic->sync) {
 +        h->sync |= 2;
 +    }
 +
      if (setup_finished)
          ff_thread_finish_setup(s->avctx);
  }
@@@ -1572,7 -1541,7 +1572,7 @@@ static av_always_inline void backup_mb_
                              AV_COPY128(top_border+16, src_cb + 15*uvlinesize);
                              AV_COPY128(top_border+32, src_cr + 15*uvlinesize);
                          }
 -                    } else if(chroma422) {
 +                    } else if(chroma422){
                          if (pixel_shift) {
                              AV_COPY128(top_border+32, src_cb + 15*uvlinesize);
                              AV_COPY128(top_border+48, src_cr + 15*uvlinesize);
@@@ -1947,8 -1916,8 +1947,8 @@@ static av_always_inline void hl_decode_
      }
  
      if (!simple && IS_INTRA_PCM(mb_type)) {
 +        const int bit_depth = h->sps.bit_depth_luma;
          if (pixel_shift) {
 -            const int bit_depth = h->sps.bit_depth_luma;
              int j;
              GetBitContext gb;
              init_get_bits(&gb, (uint8_t*)h->mb, 384*bit_depth);
                  if (!h->sps.chroma_format_idc) {
                      for (i = 0; i < block_h; i++) {
                          uint16_t *tmp_cb = (uint16_t*)(dest_cb + i*uvlinesize);
 -                        for (j = 0; j < 8; j++) {
 -                            tmp_cb[j] = 1 << (bit_depth - 1);
 -                        }
 -                    }
 -                    for (i = 0; i < block_h; i++) {
                          uint16_t *tmp_cr = (uint16_t*)(dest_cr + i*uvlinesize);
                          for (j = 0; j < 8; j++) {
 -                            tmp_cr[j] = 1 << (bit_depth - 1);
 +                            tmp_cb[j] = tmp_cr[j] = 1 << (bit_depth - 1);
                          }
                      }
                  } else {
              }
              if(simple || !CONFIG_GRAY || !(s->flags&CODEC_FLAG_GRAY)){
                  if (!h->sps.chroma_format_idc) {
 -                    for (i = 0; i < block_h; i++) {
 -                        memset(dest_cb + i*uvlinesize, 128, 8);
 -                        memset(dest_cr + i*uvlinesize, 128, 8);
 +                    for (i=0; i<8; i++) {
 +                        memset(dest_cb + i*uvlinesize, 1 << (bit_depth - 1), 8);
 +                        memset(dest_cr + i*uvlinesize, 1 << (bit_depth - 1), 8);
                      }
                  } else {
 -                    for (i = 0; i < block_h; i++) {
 +                    for (i=0; i<block_h; i++) {
                          memcpy(dest_cb + i*uvlinesize, h->mb + 128 + i*4,  8);
                          memcpy(dest_cr + i*uvlinesize, h->mb + 160 + i*4,  8);
                      }
                      h->h264dsp.h264_idct_add8(dest, block_offset,
                                                h->mb, uvlinesize,
                                                h->non_zero_count_cache);
 -                }else{
 +                }
 +#if CONFIG_SVQ3_DECODER
 +                else{
                      h->h264dsp.h264_chroma_dc_dequant_idct(h->mb + 16*16*1, h->dequant4_coeff[IS_INTRA(mb_type) ? 1:4][h->chroma_qp[0]][0]);
                      h->h264dsp.h264_chroma_dc_dequant_idct(h->mb + 16*16*2, h->dequant4_coeff[IS_INTRA(mb_type) ? 2:5][h->chroma_qp[1]][0]);
                      for(j=1; j<3; j++){
                          }
                      }
                  }
 +#endif
              }
          }
      }
@@@ -2366,21 -2337,18 +2366,21 @@@ static void implicit_weight_table(H264C
   * instantaneous decoder refresh.
   */
  static void idr(H264Context *h){
 +    int i;
      ff_h264_remove_all_refs(h);
 -    h->prev_frame_num= 0;
 +    h->prev_frame_num= -1;
      h->prev_frame_num_offset= 0;
      h->prev_poc_msb=
      h->prev_poc_lsb= 0;
 +    for (i = 0; i < MAX_DELAYED_PIC_COUNT; i++)
 +        h->last_pocs[i] = INT_MIN;
  }
  
  /* forget old pics after a seek */
  static void flush_dpb(AVCodecContext *avctx){
      H264Context *h= avctx->priv_data;
      int i;
 -    for(i=0; i<MAX_DELAYED_PIC_COUNT; i++) {
 +    for(i=0; i<=MAX_DELAYED_PIC_COUNT; i++) {
          if(h->delayed_pic[i])
              h->delayed_pic[i]->f.reference = 0;
          h->delayed_pic[i]= NULL;
      h->s.first_field= 0;
      ff_h264_reset_sei(h);
      ff_mpeg_flush(avctx);
 +    h->recovery_frame= -1;
 +    h->sync= 0;
  }
  
  static int init_poc(H264Context *h){
@@@ -2649,7 -2615,7 +2649,7 @@@ static int decode_slice_header(H264Cont
          s->me.qpel_avg= s->dsp.avg_h264_qpel_pixels_tab;
      }
  
 -    first_mb_in_slice= get_ue_golomb(&s->gb);
 +    first_mb_in_slice= get_ue_golomb_long(&s->gb);
  
      if(first_mb_in_slice == 0){ //FIXME better field boundary detection
          if(h0->current_slice && FIELD_PICTURE){
  
      s->chroma_y_shift = h->sps.chroma_format_idc <= 1; // 400 uses yuv420p
  
 -    s->width = 16*s->mb_width - (2>>CHROMA444)*FFMIN(h->sps.crop_right, (8<<CHROMA444)-1);
 -    if(h->sps.frame_mbs_only_flag)
 -        s->height= 16*s->mb_height - (1<<s->chroma_y_shift)*FFMIN(h->sps.crop_bottom, (16>>s->chroma_y_shift)-1);
 -    else
 -        s->height= 16*s->mb_height - (2<<s->chroma_y_shift)*FFMIN(h->sps.crop_bottom, (16>>s->chroma_y_shift)-1);
 +    s->width = 16*s->mb_width;
 +    s->height= 16*s->mb_height;
  
      if (s->context_initialized
 -        && (   s->width != s->avctx->width || s->height != s->avctx->height
 +        && (   s->width != s->avctx->coded_width || s->height != s->avctx->coded_height
 +            || s->avctx->bits_per_raw_sample != h->sps.bit_depth_luma
 +            || h->cur_chroma_format_idc != h->sps.chroma_format_idc
              || av_cmp_q(h->sps.sar, s->avctx->sample_aspect_ratio))) {
          if(h != h0) {
 -            av_log_missing_feature(s->avctx, "Width/height changing with threads is", 0);
 +            av_log_missing_feature(s->avctx, "Width/height/bit depth/chroma idc changing with threads is", 0);
              return -1;   // width / height changed during parallelized decoding
          }
          free_tables(h, 0);
          flush_dpb(s->avctx);
          MPV_common_end(s);
 +        h->list_count = 0;
      }
      if (!s->context_initialized) {
          if (h != h0) {
              av_log(h->s.avctx, AV_LOG_ERROR, "Cannot (re-)initialize context during parallel decoding.\n");
              return -1;
          }
 -
          avcodec_set_dimensions(s->avctx, s->width, s->height);
 +        s->avctx->width  -= (2>>CHROMA444)*FFMIN(h->sps.crop_right, (8<<CHROMA444)-1);
 +        s->avctx->height -= (1<<s->chroma_y_shift)*FFMIN(h->sps.crop_bottom, (16>>s->chroma_y_shift)-1) * (2 - h->sps.frame_mbs_only_flag);
          s->avctx->sample_aspect_ratio= h->sps.sar;
          av_assert0(s->avctx->sample_aspect_ratio.den);
  
 +        if (s->avctx->bits_per_raw_sample != h->sps.bit_depth_luma ||
 +            h->cur_chroma_format_idc != h->sps.chroma_format_idc) {
 +            if (h->sps.bit_depth_luma >= 8 && h->sps.bit_depth_luma <= 10 &&
 +                (h->sps.bit_depth_luma != 9 || !CHROMA422)) {
 +                s->avctx->bits_per_raw_sample = h->sps.bit_depth_luma;
 +                h->cur_chroma_format_idc = h->sps.chroma_format_idc;
 +                h->pixel_shift = h->sps.bit_depth_luma > 8;
 +
 +                ff_h264dsp_init(&h->h264dsp, h->sps.bit_depth_luma, h->sps.chroma_format_idc);
 +                ff_h264_pred_init(&h->hpc, s->codec_id, h->sps.bit_depth_luma, h->sps.chroma_format_idc);
 +                s->dsp.dct_bits = h->sps.bit_depth_luma > 8 ? 32 : 16;
 +                dsputil_init(&s->dsp, s->avctx);
 +            } else {
 +                av_log(s->avctx, AV_LOG_ERROR, "Unsupported bit depth: %d chroma_idc: %d\n",
 +                       h->sps.bit_depth_luma, h->sps.chroma_format_idc);
 +                return -1;
 +            }
 +        }
 +
          if(h->sps.video_signal_type_present_flag){
 -            s->avctx->color_range = h->sps.full_range ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG;
 +            s->avctx->color_range = h->sps.full_range>0 ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG;
              if(h->sps.colour_description_present_flag){
                  s->avctx->color_primaries = h->sps.color_primaries;
                  s->avctx->color_trc       = h->sps.color_trc;
  
          switch (h->sps.bit_depth_luma) {
              case 9 :
-                 if (CHROMA444)
-                     s->avctx->pix_fmt = PIX_FMT_YUV444P9;
-                 else if (CHROMA422)
+                 if (CHROMA444) {
+                     if (s->avctx->colorspace == AVCOL_SPC_RGB) {
+                         s->avctx->pix_fmt = PIX_FMT_GBRP9;
+                     } else
+                         s->avctx->pix_fmt = PIX_FMT_YUV444P9;
+                 } else if (CHROMA422)
                      s->avctx->pix_fmt = PIX_FMT_YUV422P9;
                  else
                      s->avctx->pix_fmt = PIX_FMT_YUV420P9;
                  break;
              case 10 :
-                 if (CHROMA444)
-                     s->avctx->pix_fmt = PIX_FMT_YUV444P10;
-                 else if (CHROMA422)
+                 if (CHROMA444) {
+                     if (s->avctx->colorspace == AVCOL_SPC_RGB) {
+                         s->avctx->pix_fmt = PIX_FMT_GBRP10;
+                     } else
+                         s->avctx->pix_fmt = PIX_FMT_YUV444P10;
+                 } else if (CHROMA422)
                      s->avctx->pix_fmt = PIX_FMT_YUV422P10;
                  else
                      s->avctx->pix_fmt = PIX_FMT_YUV420P10;
                  break;
              default:
                  if (CHROMA444){
 +                    s->avctx->pix_fmt = s->avctx->color_range == AVCOL_RANGE_JPEG ? PIX_FMT_YUVJ444P : PIX_FMT_YUV444P;
                      if (s->avctx->colorspace == AVCOL_SPC_RGB) {
 -                        s->avctx->pix_fmt = PIX_FMT_GBRP;
 -                    } else
 -                        s->avctx->pix_fmt = s->avctx->color_range == AVCOL_RANGE_JPEG ? PIX_FMT_YUVJ444P : PIX_FMT_YUV444P;
 +                       s->avctx->pix_fmt = PIX_FMT_GBR24P;
 +                       av_log(h->s.avctx, AV_LOG_DEBUG, "Detected GBR colorspace.\n");
 +                    } else if (s->avctx->colorspace == AVCOL_SPC_YCGCO) {
 +                        av_log(h->s.avctx, AV_LOG_WARNING, "Detected unsupported YCgCo colorspace.\n");
 +                    }
                  } else if (CHROMA422) {
                      s->avctx->pix_fmt = s->avctx->color_range == AVCOL_RANGE_JPEG ? PIX_FMT_YUVJ422P : PIX_FMT_YUV422P;
                  }else{
                  c->sps = h->sps;
                  c->pps = h->pps;
                  c->pixel_shift = h->pixel_shift;
 +                c->cur_chroma_format_idc = h->cur_chroma_format_idc;
                  init_scan_tables(c);
                  clone_tables(c, h, i);
              }
      if(h->sps.frame_mbs_only_flag){
          s->picture_structure= PICT_FRAME;
      }else{
 +        if(!h->sps.direct_8x8_inference_flag && slice_type == AV_PICTURE_TYPE_B){
 +            av_log(h->s.avctx, AV_LOG_ERROR, "This stream was generated by a broken encoder, invalid 8x8 inference\n");
 +            return -1;
 +        }
          if(get_bits1(&s->gb)) { //field_pic_flag
              s->picture_structure= PICT_TOP_FIELD + get_bits1(&s->gb); //bottom_field_flag
          } else {
  
      if(h0->current_slice == 0){
          // Shorten frame num gaps so we don't have to allocate reference frames just to throw them away
 -        if(h->frame_num != h->prev_frame_num) {
 +        if(h->frame_num != h->prev_frame_num && h->prev_frame_num >= 0) {
              int unwrap_prev_frame_num = h->prev_frame_num, max_frame_num = 1<<h->sps.log2_max_frame_num;
  
              if (unwrap_prev_frame_num > h->frame_num) unwrap_prev_frame_num -= max_frame_num;
              }
          }
  
 -        while(h->frame_num !=  h->prev_frame_num &&
 +        while(h->frame_num !=  h->prev_frame_num && h->prev_frame_num >= 0 &&
                h->frame_num != (h->prev_frame_num+1)%(1<<h->sps.log2_max_frame_num)){
              Picture *prev = h->short_ref_count ? h->short_ref[0] : NULL;
              av_log(h->s.avctx, AV_LOG_DEBUG, "Frame num gap %d %d\n", h->frame_num, h->prev_frame_num);
                  s0->first_field = FIELD_PICTURE;
  
              } else {
 -                if (h->nal_ref_idc &&
 -                        s0->current_picture_ptr->f.reference &&
 -                        s0->current_picture_ptr->frame_num != h->frame_num) {
 +                if (s0->current_picture_ptr->frame_num != h->frame_num) {
                      /*
 -                     * This and previous field were reference, but had
 +                     * This and previous field had
                       * different frame_nums. Consider this field first in
                       * pair. Throw away previous field except for reference
                       * purposes.
      h->ref_count[1]= h->pps.ref_count[1];
  
      if(h->slice_type_nos != AV_PICTURE_TYPE_I){
 +        unsigned max= (16<<(s->picture_structure != PICT_FRAME))-1;
          if(h->slice_type_nos == AV_PICTURE_TYPE_B){
              h->direct_spatial_mv_pred= get_bits1(&s->gb);
          }
              if(h->slice_type_nos==AV_PICTURE_TYPE_B)
                  h->ref_count[1]= get_ue_golomb(&s->gb) + 1;
  
 -            if(h->ref_count[0]-1 > 32-1 || h->ref_count[1]-1 > 32-1){
 -                av_log(h->s.avctx, AV_LOG_ERROR, "reference overflow\n");
 -                h->ref_count[0]= h->ref_count[1]= 1;
 -                return -1;
 -            }
 +        }
 +        if(h->ref_count[0]-1 > max || h->ref_count[1]-1 > max){
 +            av_log(h->s.avctx, AV_LOG_ERROR, "reference overflow\n");
 +            h->ref_count[0]= h->ref_count[1]= 1;
 +            return -1;
          }
          if(h->slice_type_nos == AV_PICTURE_TYPE_B)
              h->list_count= 2;
          else
              h->list_count= 1;
      }else
 -        h->list_count= 0;
 +        h->ref_count[1]= h->ref_count[0]= h->list_count= 0;
  
      if(!default_ref_list_done){
          ff_h264_fill_default_ref_list(h);
  
      h0->last_slice_type = slice_type;
      h->slice_num = ++h0->current_slice;
 -    if(h->slice_num >= MAX_SLICES){
 -        av_log(s->avctx, AV_LOG_ERROR, "Too many slices, increase MAX_SLICES and recompile\n");
 +
 +    if(h->slice_num)
 +        h0->slice_row[(h->slice_num-1)&(MAX_SLICES-1)]= s->resync_mb_y;
 +    if (   h0->slice_row[h->slice_num&(MAX_SLICES-1)] + 3 >= s->resync_mb_y
 +        && h0->slice_row[h->slice_num&(MAX_SLICES-1)] <= s->resync_mb_y
 +        && h->slice_num >= MAX_SLICES) {
 +        //in case of ASO this check needs to be updated depending on how we decide to assign slice numbers in this case
 +        av_log(s->avctx, AV_LOG_WARNING, "Possibly too many slices (%d >= %d), increase MAX_SLICES and recompile if there are artifacts\n", h->slice_num, MAX_SLICES);
      }
  
      for(j=0; j<2; j++){
@@@ -3684,8 -3623,7 +3690,8 @@@ static int decode_slice(struct AVCodecC
                  if(s->mb_y >= s->mb_height){
                      tprintf(s->avctx, "slice end %d %d\n", get_bits_count(&s->gb), s->gb.size_in_bits);
  
 -                    if(get_bits_count(&s->gb) == s->gb.size_in_bits ) {
 +                    if(   get_bits_count(&s->gb) == s->gb.size_in_bits
 +                       || get_bits_count(&s->gb) <  s->gb.size_in_bits && s->avctx->error_recognition < FF_ER_AGGRESSIVE) {
                          ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x-1, s->mb_y, (AC_END|DC_END|MV_END)&part_mask);
  
                          return 0;
@@@ -3735,7 -3673,6 +3741,7 @@@ static int execute_decode_slices(H264Co
              hx = h->thread_context[i];
              hx->s.error_recognition = avctx->error_recognition;
              hx->s.error_count = 0;
 +            hx->x264_build= h->x264_build;
          }
  
          avctx->execute(avctx, (void *)decode_slice,
@@@ -3823,13 -3760,13 +3829,13 @@@ static int decode_nal_units(H264Contex
              s->workaround_bugs |= FF_BUG_TRUNCATED;
  
          if(!(s->workaround_bugs & FF_BUG_TRUNCATED)){
 -        while(ptr[dst_length - 1] == 0 && dst_length > 0)
 +        while(dst_length > 0 && ptr[dst_length - 1] == 0)
              dst_length--;
          }
          bit_length= !dst_length ? 0 : (8*dst_length - ff_h264_decode_rbsp_trailing(h, ptr + dst_length - 1));
  
          if(s->avctx->debug&FF_DEBUG_STARTCODE){
 -            av_log(h->s.avctx, AV_LOG_DEBUG, "NAL %d at %d/%d length %d\n", hx->nal_unit_type, buf_index, buf_size, dst_length);
 +            av_log(h->s.avctx, AV_LOG_DEBUG, "NAL %d/%d at %d/%d length %d\n", hx->nal_unit_type, hx->nal_ref_idc, buf_index, buf_size, dst_length);
          }
  
          if (h->is_avc && (nalsize != consumed) && nalsize){
              if((err = decode_slice_header(hx, h)))
                 break;
  
 +            if (   h->sei_recovery_frame_cnt >= 0
 +                && ((h->recovery_frame - h->frame_num) & ((1 << h->sps.log2_max_frame_num)-1)) > h->sei_recovery_frame_cnt) {
 +                h->recovery_frame = (h->frame_num + h->sei_recovery_frame_cnt) %
 +                                    (1 << h->sps.log2_max_frame_num);
 +            }
 +
              s->current_picture_ptr->f.key_frame |=
 -                    (hx->nal_unit_type == NAL_IDR_SLICE) ||
 -                    (h->sei_recovery_frame_cnt >= 0);
 +                    (hx->nal_unit_type == NAL_IDR_SLICE);
 +
 +            if (h->recovery_frame == h->frame_num) {
 +                h->sync |= 1;
 +                h->recovery_frame = -1;
 +            }
 +
 +            h->sync |= !!s->current_picture_ptr->f.key_frame;
 +            h->sync |= 3*!!(s->flags2 & CODEC_FLAG2_SHOW_ALL);
 +            s->current_picture_ptr->sync = h->sync;
  
              if (h->current_slice == 1) {
                  if(!(s->flags2 & CODEC_FLAG2_CHUNKS)) {
              break;
          case NAL_SPS:
              init_get_bits(&s->gb, ptr, bit_length);
 -            ff_h264_decode_seq_parameter_set(h);
 +            if(ff_h264_decode_seq_parameter_set(h) < 0 && (h->is_avc ? (nalsize != consumed) && nalsize : 1)){
 +                av_log(h->s.avctx, AV_LOG_DEBUG, "SPS decoding failure, trying alternative mode\n");
 +                if(h->is_avc) av_assert0(next_avc - buf_index + consumed == nalsize);
 +                init_get_bits(&s->gb, &buf[buf_index + 1 - consumed], 8*(next_avc - buf_index + consumed));
 +                ff_h264_decode_seq_parameter_set(h);
 +            }
  
              if (s->flags& CODEC_FLAG_LOW_DELAY ||
                  (h->sps.bitstream_restriction_flag && !h->sps.num_reorder_frames))
  
              if(avctx->has_b_frames < 2)
                  avctx->has_b_frames= !s->low_delay;
 -
 -            if (avctx->bits_per_raw_sample != h->sps.bit_depth_luma ||
 -                h->cur_chroma_format_idc != h->sps.chroma_format_idc) {
 -                if (h->sps.bit_depth_luma >= 8 && h->sps.bit_depth_luma <= 10) {
 -                    avctx->bits_per_raw_sample = h->sps.bit_depth_luma;
 -                    h->cur_chroma_format_idc = h->sps.chroma_format_idc;
 -                    h->pixel_shift = h->sps.bit_depth_luma > 8;
 -
 -                    ff_h264dsp_init(&h->h264dsp, h->sps.bit_depth_luma, h->sps.chroma_format_idc);
 -                    ff_h264_pred_init(&h->hpc, s->codec_id, h->sps.bit_depth_luma, h->sps.chroma_format_idc);
 -                    s->dsp.dct_bits = h->sps.bit_depth_luma > 8 ? 32 : 16;
 -                    dsputil_init(&s->dsp, s->avctx);
 -                } else {
 -                    av_log(avctx, AV_LOG_ERROR, "Unsupported bit depth: %d\n", h->sps.bit_depth_luma);
 -                    return -1;
 -                }
 -            }
              break;
          case NAL_PPS:
              init_get_bits(&s->gb, ptr, bit_length);
@@@ -4064,8 -3999,6 +4070,8 @@@ static int decode_frame(AVCodecContext 
  
          return 0;
      }
 +    if(h->is_avc && buf_size >= 9 && AV_RB32(buf)==0x0164001F && buf[5] && buf[8]==0x67)
 +        return ff_h264_decode_extradata(h, buf, buf_size);
  
      buf_index=decode_nal_units(h, buf, buf_size);
      if(buf_index < 0)
  
          field_end(h, 0);
  
 -        if (!h->next_output_pic) {
 -            /* Wait for second field. */
 -            *data_size = 0;
 -
 -        } else {
 -            *data_size = sizeof(AVFrame);
 -            *pict = *(AVFrame*)h->next_output_pic;
 +        *data_size = 0; /* Wait for second field. */
 +        if (h->next_output_pic && h->next_output_pic->sync) {
 +            if(h->sync>1 || h->next_output_pic->f.pict_type != AV_PICTURE_TYPE_B){
 +                *data_size = sizeof(AVFrame);
 +                *pict = *(AVFrame*)h->next_output_pic;
 +            }
          }
      }
  
@@@ -4129,7 -4063,6 +4135,7 @@@ static inline void fill_mb_avail(H264Co
  #undef random
  #define COUNT 8000
  #define SIZE (COUNT*40)
 +extern AVCodec ff_h264_decoder;
  int main(void){
      int i;
      uint8_t temp[SIZE];
      DSPContext dsp;
      AVCodecContext avctx;
  
 +    avcodec_get_context_defaults3(&avctx, &ff_h264_decoder);
 +
      dsputil_init(&dsp, &avctx);
  
      init_put_bits(&pb, temp, SIZE);
@@@ -4244,26 -4175,6 +4250,26 @@@ static const AVProfile profiles[] = 
      { FF_PROFILE_UNKNOWN },
  };
  
 +static const AVOption h264_options[] = {
 +    {"is_avc", "is avc", offsetof(H264Context, is_avc), FF_OPT_TYPE_INT, {.dbl = 0}, 0, 1, 0},
 +    {"nal_length_size", "nal_length_size", offsetof(H264Context, nal_length_size), FF_OPT_TYPE_INT, {.dbl = 0}, 0, 4, 0},
 +    {NULL}
 +};
 +
 +static const AVClass h264_class = {
 +    "H264 Decoder",
 +    av_default_item_name,
 +    h264_options,
 +    LIBAVUTIL_VERSION_INT,
 +};
 +
 +static const AVClass h264_vdpau_class = {
 +    "H264 VDPAU Decoder",
 +    av_default_item_name,
 +    h264_options,
 +    LIBAVUTIL_VERSION_INT,
 +};
 +
  AVCodec ff_h264_decoder = {
      .name           = "h264",
      .type           = AVMEDIA_TYPE_VIDEO,
      .init_thread_copy      = ONLY_IF_THREADS_ENABLED(decode_init_thread_copy),
      .update_thread_context = ONLY_IF_THREADS_ENABLED(decode_update_thread_context),
      .profiles = NULL_IF_CONFIG_SMALL(profiles),
 +    .priv_class     = &h264_class,
  };
  
  #if CONFIG_H264_VDPAU_DECODER
@@@ -4296,6 -4206,5 +4302,6 @@@ AVCodec ff_h264_vdpau_decoder = 
      .long_name = NULL_IF_CONFIG_SMALL("H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 (VDPAU acceleration)"),
      .pix_fmts = (const enum PixelFormat[]){PIX_FMT_VDPAU_H264, PIX_FMT_NONE},
      .profiles = NULL_IF_CONFIG_SMALL(profiles),
 +    .priv_class     = &h264_vdpau_class,
  };
  #endif
diff --combined libavcodec/snow.c
index 95d4794e72d1dca4a13d87cac18f02e8e269c957,a2903583fb2537219821d373933368ef0670e29f..87b3a8f4023d207005a2a5bc6b8863454fb01c45
@@@ -1,20 -1,20 +1,20 @@@
  /*
   * Copyright (C) 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.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * FFmpeg is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
 - * License along with Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
  #include "dsputil.h"
  #include "dwt.h"
  #include "snow.h"
+ #include "snowdata.h"
  
  #include "rangecoder.h"
  #include "mathops.h"
- #include "mpegvideo.h"
  #include "h263.h"
  
  #undef NDEBUG
  #include <assert.h>
  
- static const int8_t quant3bA[256]={
-  0, 0, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1,
-  1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1,
-  1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1,
-  1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1,
-  1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1,
-  1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1,
-  1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1,
-  1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1,
-  1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1,
-  1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1,
-  1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1,
-  1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1,
-  1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1,
-  1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1,
-  1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1,
-  1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1,
- };
- static const uint8_t obmc32[1024]={
-   0,  0,  0,  0,  4,  4,  4,  4,  4,  4,  4,  4,  8,  8,  8,  8,  8,  8,  8,  8,  4,  4,  4,  4,  4,  4,  4,  4,  0,  0,  0,  0,
-   0,  4,  4,  4,  8,  8,  8, 12, 12, 16, 16, 16, 20, 20, 20, 24, 24, 20, 20, 20, 16, 16, 16, 12, 12,  8,  8,  8,  4,  4,  4,  0,
-   0,  4,  8,  8, 12, 12, 16, 20, 20, 24, 28, 28, 32, 32, 36, 40, 40, 36, 32, 32, 28, 28, 24, 20, 20, 16, 12, 12,  8,  8,  4,  0,
-   0,  4,  8, 12, 16, 20, 24, 28, 28, 32, 36, 40, 44, 48, 52, 56, 56, 52, 48, 44, 40, 36, 32, 28, 28, 24, 20, 16, 12,  8,  4,  0,
-   4,  8, 12, 16, 20, 24, 28, 32, 40, 44, 48, 52, 56, 60, 64, 68, 68, 64, 60, 56, 52, 48, 44, 40, 32, 28, 24, 20, 16, 12,  8,  4,
-   4,  8, 12, 20, 24, 32, 36, 40, 48, 52, 56, 64, 68, 76, 80, 84, 84, 80, 76, 68, 64, 56, 52, 48, 40, 36, 32, 24, 20, 12,  8,  4,
-   4,  8, 16, 24, 28, 36, 44, 48, 56, 60, 68, 76, 80, 88, 96,100,100, 96, 88, 80, 76, 68, 60, 56, 48, 44, 36, 28, 24, 16,  8,  4,
-   4, 12, 20, 28, 32, 40, 48, 56, 64, 72, 80, 88, 92,100,108,116,116,108,100, 92, 88, 80, 72, 64, 56, 48, 40, 32, 28, 20, 12,  4,
-   4, 12, 20, 28, 40, 48, 56, 64, 72, 80, 88, 96,108,116,124,132,132,124,116,108, 96, 88, 80, 72, 64, 56, 48, 40, 28, 20, 12,  4,
-   4, 16, 24, 32, 44, 52, 60, 72, 80, 92,100,108,120,128,136,148,148,136,128,120,108,100, 92, 80, 72, 60, 52, 44, 32, 24, 16,  4,
-   4, 16, 28, 36, 48, 56, 68, 80, 88,100,112,120,132,140,152,164,164,152,140,132,120,112,100, 88, 80, 68, 56, 48, 36, 28, 16,  4,
-   4, 16, 28, 40, 52, 64, 76, 88, 96,108,120,132,144,156,168,180,180,168,156,144,132,120,108, 96, 88, 76, 64, 52, 40, 28, 16,  4,
-   8, 20, 32, 44, 56, 68, 80, 92,108,120,132,144,156,168,180,192,192,180,168,156,144,132,120,108, 92, 80, 68, 56, 44, 32, 20,  8,
-   8, 20, 32, 48, 60, 76, 88,100,116,128,140,156,168,184,196,208,208,196,184,168,156,140,128,116,100, 88, 76, 60, 48, 32, 20,  8,
-   8, 20, 36, 52, 64, 80, 96,108,124,136,152,168,180,196,212,224,224,212,196,180,168,152,136,124,108, 96, 80, 64, 52, 36, 20,  8,
-   8, 24, 40, 56, 68, 84,100,116,132,148,164,180,192,208,224,240,240,224,208,192,180,164,148,132,116,100, 84, 68, 56, 40, 24,  8,
-   8, 24, 40, 56, 68, 84,100,116,132,148,164,180,192,208,224,240,240,224,208,192,180,164,148,132,116,100, 84, 68, 56, 40, 24,  8,
-   8, 20, 36, 52, 64, 80, 96,108,124,136,152,168,180,196,212,224,224,212,196,180,168,152,136,124,108, 96, 80, 64, 52, 36, 20,  8,
-   8, 20, 32, 48, 60, 76, 88,100,116,128,140,156,168,184,196,208,208,196,184,168,156,140,128,116,100, 88, 76, 60, 48, 32, 20,  8,
-   8, 20, 32, 44, 56, 68, 80, 92,108,120,132,144,156,168,180,192,192,180,168,156,144,132,120,108, 92, 80, 68, 56, 44, 32, 20,  8,
-   4, 16, 28, 40, 52, 64, 76, 88, 96,108,120,132,144,156,168,180,180,168,156,144,132,120,108, 96, 88, 76, 64, 52, 40, 28, 16,  4,
-   4, 16, 28, 36, 48, 56, 68, 80, 88,100,112,120,132,140,152,164,164,152,140,132,120,112,100, 88, 80, 68, 56, 48, 36, 28, 16,  4,
-   4, 16, 24, 32, 44, 52, 60, 72, 80, 92,100,108,120,128,136,148,148,136,128,120,108,100, 92, 80, 72, 60, 52, 44, 32, 24, 16,  4,
-   4, 12, 20, 28, 40, 48, 56, 64, 72, 80, 88, 96,108,116,124,132,132,124,116,108, 96, 88, 80, 72, 64, 56, 48, 40, 28, 20, 12,  4,
-   4, 12, 20, 28, 32, 40, 48, 56, 64, 72, 80, 88, 92,100,108,116,116,108,100, 92, 88, 80, 72, 64, 56, 48, 40, 32, 28, 20, 12,  4,
-   4,  8, 16, 24, 28, 36, 44, 48, 56, 60, 68, 76, 80, 88, 96,100,100, 96, 88, 80, 76, 68, 60, 56, 48, 44, 36, 28, 24, 16,  8,  4,
-   4,  8, 12, 20, 24, 32, 36, 40, 48, 52, 56, 64, 68, 76, 80, 84, 84, 80, 76, 68, 64, 56, 52, 48, 40, 36, 32, 24, 20, 12,  8,  4,
-   4,  8, 12, 16, 20, 24, 28, 32, 40, 44, 48, 52, 56, 60, 64, 68, 68, 64, 60, 56, 52, 48, 44, 40, 32, 28, 24, 20, 16, 12,  8,  4,
-   0,  4,  8, 12, 16, 20, 24, 28, 28, 32, 36, 40, 44, 48, 52, 56, 56, 52, 48, 44, 40, 36, 32, 28, 28, 24, 20, 16, 12,  8,  4,  0,
-   0,  4,  8,  8, 12, 12, 16, 20, 20, 24, 28, 28, 32, 32, 36, 40, 40, 36, 32, 32, 28, 28, 24, 20, 20, 16, 12, 12,  8,  8,  4,  0,
-   0,  4,  4,  4,  8,  8,  8, 12, 12, 16, 16, 16, 20, 20, 20, 24, 24, 20, 20, 20, 16, 16, 16, 12, 12,  8,  8,  8,  4,  4,  4,  0,
-   0,  0,  0,  0,  4,  4,  4,  4,  4,  4,  4,  4,  8,  8,  8,  8,  8,  8,  8,  8,  4,  4,  4,  4,  4,  4,  4,  4,  0,  0,  0,  0,
-  //error:0.000020
- };
- static const uint8_t obmc16[256]={
-   0,  4,  4,  8,  8, 12, 12, 16, 16, 12, 12,  8,  8,  4,  4,  0,
-   4,  8, 16, 20, 28, 32, 40, 44, 44, 40, 32, 28, 20, 16,  8,  4,
-   4, 16, 24, 36, 44, 56, 64, 76, 76, 64, 56, 44, 36, 24, 16,  4,
-   8, 20, 36, 48, 64, 76, 92,104,104, 92, 76, 64, 48, 36, 20,  8,
-   8, 28, 44, 64, 80,100,116,136,136,116,100, 80, 64, 44, 28,  8,
-  12, 32, 56, 76,100,120,144,164,164,144,120,100, 76, 56, 32, 12,
-  12, 40, 64, 92,116,144,168,196,196,168,144,116, 92, 64, 40, 12,
-  16, 44, 76,104,136,164,196,224,224,196,164,136,104, 76, 44, 16,
-  16, 44, 76,104,136,164,196,224,224,196,164,136,104, 76, 44, 16,
-  12, 40, 64, 92,116,144,168,196,196,168,144,116, 92, 64, 40, 12,
-  12, 32, 56, 76,100,120,144,164,164,144,120,100, 76, 56, 32, 12,
-   8, 28, 44, 64, 80,100,116,136,136,116,100, 80, 64, 44, 28,  8,
-   8, 20, 36, 48, 64, 76, 92,104,104, 92, 76, 64, 48, 36, 20,  8,
-   4, 16, 24, 36, 44, 56, 64, 76, 76, 64, 56, 44, 36, 24, 16,  4,
-   4,  8, 16, 20, 28, 32, 40, 44, 44, 40, 32, 28, 20, 16,  8,  4,
-   0,  4,  4,  8,  8, 12, 12, 16, 16, 12, 12,  8,  8,  4,  4,  0,
- //error:0.000015
- };
- //linear *64
- static const uint8_t obmc8[64]={
-   4, 12, 20, 28, 28, 20, 12,  4,
-  12, 36, 60, 84, 84, 60, 36, 12,
-  20, 60,100,140,140,100, 60, 20,
-  28, 84,140,196,196,140, 84, 28,
-  28, 84,140,196,196,140, 84, 28,
-  20, 60,100,140,140,100, 60, 20,
-  12, 36, 60, 84, 84, 60, 36, 12,
-   4, 12, 20, 28, 28, 20, 12,  4,
- //error:0.000000
- };
- //linear *64
- static const uint8_t obmc4[16]={
-  16, 48, 48, 16,
-  48,144,144, 48,
-  48,144,144, 48,
-  16, 48, 48, 16,
- //error:0.000000
- };
- static const uint8_t * const obmc_tab[4]={
-     obmc32, obmc16, obmc8, obmc4
- };
- static int scale_mv_ref[MAX_REF_FRAMES][MAX_REF_FRAMES];
- 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;
-     DSPContext dsp;
-     DWTContext 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;
-     IDWTELEM *spatial_idwt_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;
-     Plane plane[MAX_PLANES];
-     BlockNode *block;
- #define ME_CACHE_SIZE 1024
-     int me_cache[ME_CACHE_SIZE];
-     int me_cache_generation;
-     slice_buffer sb;
-     int memc_only;
-     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;
- }SnowContext;
- #ifdef __sgi
- // Avoid a name clash on SGI IRIX
- #undef qexp
- #endif
- #define QEXPSHIFT (7-FRAC_BITS+8) //FIXME try to change this to 0
- static uint8_t qexp[QROOT];
- 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;
-     assert(v>=0);
-     assert(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;
-     assert(log2>=-4);
-     while(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 + quant3bA[l&0xFF] + 3*quant3bA[t&0xFF]]);
+ 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];
  
-                     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;
-                     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);
-                     x+= max_run;
-                     run-= max_run;
-                 }
+             v <<= 8 - LOG2_OBMC_MAX;
+             if(FRAC_BITS != 8){
+                 v >>= 8 - FRAC_BITS;
              }
-         }
-         (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;
+             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{
-                 parent_xc= prev_parent_xc;
+                 dst[x + src_x] -= v;
              }
          }
      }
-     (xc++)->x= w+1; //end marker
- }
- 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= 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 void reset_contexts(SnowContext *s){ //FIXME better initial contexts
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++){
      memset(s->block_state, MID_STATE, sizeof(s->block_state));
  }
  
static int alloc_blocks(SnowContext *s){
int ff_snow_alloc_blocks(SnowContext *s){
      int w= -((-s->avctx->width )>>LOG2_MB_SIZE);
      int h= -((-s->avctx->height)>>LOG2_MB_SIZE);
  
      return 0;
  }
  
- 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;
-     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 init_ref(MotionEstContext *c, uint8_t *src[3], uint8_t *ref[3], uint8_t *ref2[3], int x, int y, int ref_index){
-     const int offset[3]= {
-           y*c->  stride + x,
-         ((y*c->uvstride + x)>>1),
-         ((y*c->uvstride + x)>>1),
-     };
+ static void init_qexp(void){
      int i;
-     for(i=0; i<3; i++){
-         c->src[0][i]= src [i];
-         c->ref[0][i]= ref [i] + offset[i];
-     }
-     assert(!ref_index);
- }
- 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 = 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));
-     }
- }
- static void 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;
-     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;
-     }
-     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);
-             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);
-             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{
-         decode_q_branch(s, level+1, 2*x+0, 2*y+0);
-         decode_q_branch(s, level+1, 2*x+1, 2*y+0);
-         decode_q_branch(s, level+1, 2*x+0, 2*y+1);
-         decode_q_branch(s, level+1, 2*x+1, 2*y+1);
-     }
- }
- static void decode_blocks(SnowContext *s){
-     int x, y;
-     int w= s->b_width;
-     int h= s->b_height;
+     double v=128;
  
-     for(y=0; y<h; y++){
-         for(x=0; x<w; x++){
-             decode_q_branch(s, 0, x, y);
-         }
+     for(i=0; i<QROOT; i++){
+         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,
      }
  }
  
- #define mca(dx,dy,b_w)\
- static void mc_block_hpel ## dx ## dy ## b_w(uint8_t *dst, const uint8_t *src, int stride, int h){\
-     assert(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)
- static void pred_block(SnowContext *s, uint8_t *dst, uint8_t *tmp, int stride, int sx, int sy, int b_w, int b_h, BlockNode *block, int plane_index, int w, int h){
+ void ff_snow_pred_block(SnowContext *s, uint8_t *dst, uint8_t *tmp, int 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 int color = block->color[plane_index];
      }
  }
  
- 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;
-             }
-         }
-     }
+ #define mca(dx,dy,b_w)\
+ static void mc_block_hpel ## dx ## dy ## b_w(uint8_t *dst, const uint8_t *src, int stride, int h){\
+     assert(h==b_w);\
+     mc_block(NULL, dst, src-(HTAPS_MAX/2-1)-(HTAPS_MAX/2-1)*stride, stride, b_w, b_w, dx, dy);\
  }
  
- //FIXME name cleanup (b_w, block_w, b_width stuff)
- 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;
-     }
+ 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)
  
-     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;
-     }else 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;
-     }else if(src_y + b_h> h){
-         b_h = h - src_y;
-     }
+ av_cold int ff_snow_common_init(AVCodecContext *avctx){
+     SnowContext *s = avctx->priv_data;
+     int width, height;
+     int i, j;
  
-     if(b_w<=0 || b_h<=0) return;
+     s->avctx= avctx;
+     s->max_ref_frames=1; //just make sure its not an invalid value in case of no initial keyframe
  
-     assert(src_stride > 2*MB_SIZE + 5);
+     dsputil_init(&s->dsp, avctx);
+     ff_dwt_init(&s->dwt);
  
-     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;
+ #define mcf(dx,dy)\
+     s->dsp.put_qpel_pixels_tab       [0][dy+dx/4]=\
+     s->dsp.put_no_rnd_qpel_pixels_tab[0][dy+dx/4]=\
+         s->dsp.put_h264_qpel_pixels_tab[0][dy+dx/4];\
+     s->dsp.put_qpel_pixels_tab       [1][dy+dx/4]=\
+     s->dsp.put_no_rnd_qpel_pixels_tab[1][dy+dx/4]=\
+         s->dsp.put_h264_qpel_pixels_tab[1][dy+dx/4];
  
-     ptmp= tmp + 3*tmp_step;
-     block[0]= ptmp;
-     ptmp+=tmp_step;
-     pred_block(s, block[0], tmp, src_stride, src_x, src_y, b_w, b_h, lt, plane_index, w, h);
+     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)
  
-     if(same_block(lt, rt)){
-         block[1]= block[0];
-     }else{
-         block[1]= ptmp;
-         ptmp+=tmp_step;
-         pred_block(s, block[1], tmp, src_stride, src_x, src_y, b_w, b_h, rt, plane_index, w, h);
-     }
+ #define mcfh(dx,dy)\
+     s->dsp.put_pixels_tab       [0][dy/4+dx/8]=\
+     s->dsp.put_no_rnd_pixels_tab[0][dy/4+dx/8]=\
+         mc_block_hpel ## dx ## dy ## 16;\
+     s->dsp.put_pixels_tab       [1][dy/4+dx/8]=\
+     s->dsp.put_no_rnd_pixels_tab[1][dy/4+dx/8]=\
+         mc_block_hpel ## dx ## dy ## 8;
  
-     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;
-         pred_block(s, block[2], tmp, src_stride, src_x, src_y, b_w, b_h, lb, plane_index, w, h);
-     }
+     mcfh(0, 0)
+     mcfh(8, 0)
+     mcfh(0, 8)
+     mcfh(8, 8)
  
-     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;
-         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;
-                 }
-             }
-         }
-     }
- }
+     init_qexp();
  
- 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/2 : block_size;
-     const uint8_t *obmc  = plane_index ? obmc_tab[s->block_max_depth+1] : obmc_tab[s->block_max_depth];
-     int obmc_stride= plane_index ? block_size : 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_w*mb_y; y<FFMIN(h,block_w*(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_w*mb_y; y<FFMIN(h,block_w*(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;
-                 }
-             }
-         }
+ //    dec += FFMAX(s->chroma_h_shift, s->chroma_v_shift);
  
-         return;
-     }
+     width= s->avctx->width;
+     height= s->avctx->height;
  
-     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_w*mb_y - block_w/2,
-                    block_w, block_w,
-                    w, h,
-                    w, ref_stride, obmc_stride,
-                    mb_x - 1, mb_y - 1,
-                    add, 0, plane_index);
-     }
- }
- 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/2 : block_size;
-     const uint8_t *obmc  = plane_index ? obmc_tab[s->block_max_depth+1] : obmc_tab[s->block_max_depth];
-     const int obmc_stride= plane_index ? block_size : 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_w*mb_y; y<FFMIN(h,block_w*(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_w*mb_y; y<FFMIN(h,block_w*(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_w*mb_y - block_w/2,
-                    block_w, block_w,
-                    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 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= 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<3; 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 -1;\
-     }\
-     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){
-         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);
-         s->chroma_h_shift= get_symbol(&s->c, s->header_state, 0);
-         s->chroma_v_shift= get_symbol(&s->c, s->header_state, 0);
-         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<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 -1;
-                 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", s->spatial_decomposition_type);
-         return -1;
-     }
-     if(FFMIN(s->avctx-> width>>s->chroma_h_shift,
-              s->avctx->height>>s->chroma_v_shift) >> (s->spatial_decomposition_count-1) <= 0){
-         av_log(s->avctx, AV_LOG_ERROR, "spatial_decomposition_count %d too large for size", s->spatial_decomposition_count);
-         return -1;
-     }
-     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", s->block_max_depth);
-         s->block_max_depth= 0;
-         return -1;
-     }
-     return 0;
- }
- static void init_qexp(void){
-     int i;
-     double v=128;
-     for(i=0; i<QROOT; i++){
-         qexp[i]= lrintf(v);
-         v *= pow(2, 1.0 / QROOT);
-     }
- }
- static av_cold int 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 its not an invalid value in case of no initial keyframe
-     dsputil_init(&s->dsp, avctx);
-     ff_dwt_init(&s->dwt);
- #define mcf(dx,dy)\
-     s->dsp.put_qpel_pixels_tab       [0][dy+dx/4]=\
-     s->dsp.put_no_rnd_qpel_pixels_tab[0][dy+dx/4]=\
-         s->dsp.put_h264_qpel_pixels_tab[0][dy+dx/4];\
-     s->dsp.put_qpel_pixels_tab       [1][dy+dx/4]=\
-     s->dsp.put_no_rnd_qpel_pixels_tab[1][dy+dx/4]=\
-         s->dsp.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->dsp.put_pixels_tab       [0][dy/4+dx/8]=\
-     s->dsp.put_no_rnd_pixels_tab[0][dy/4+dx/8]=\
-         mc_block_hpel ## dx ## dy ## 16;\
-     s->dsp.put_pixels_tab       [1][dy/4+dx/8]=\
-     s->dsp.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)
-     if(!qexp[0])
-         init_qexp();
- //    dec += FFMAX(s->chroma_h_shift, s->chroma_v_shift);
-     width= s->avctx->width;
-     height= s->avctx->height;
-     s->spatial_idwt_buffer= av_mallocz(width*height*sizeof(IDWTELEM));
-     s->spatial_dwt_buffer= av_mallocz(width*height*sizeof(DWTELEM)); //FIXME this does not belong here
+     s->spatial_idwt_buffer= av_mallocz(width*height*sizeof(IDWTELEM));
+     s->spatial_dwt_buffer= av_mallocz(width*height*sizeof(DWTELEM)); //FIXME this does not belong here
  
      for(i=0; i<MAX_REF_FRAMES; i++)
          for(j=0; j<MAX_REF_FRAMES; j++)
      return 0;
  }
  
static int common_init_after_header(AVCodecContext *avctx){
int ff_snow_common_init_after_header(AVCodecContext *avctx) {
      SnowContext *s = avctx->priv_data;
      int plane_index, level, orientation;
  
      return 0;
  }
  
- #define QUANTIZE2 0
- #if QUANTIZE2==1
- #define Q2_STEP 8
- static void find_sse(SnowContext *s, Plane *p, int *score, int score_stride, IDWTELEM *r0, IDWTELEM *r1, int level, int orientation){
-     SubBand *b= &p->band[level][orientation];
-     int x, y;
-     int xo=0;
-     int yo=0;
-     int step= 1 << (s->spatial_decomposition_count - level);
-     if(orientation&1)
-         xo= step>>1;
-     if(orientation&2)
-         yo= step>>1;
-     //FIXME bias for nonzero ?
-     //FIXME optimize
-     memset(score, 0, sizeof(*score)*score_stride*((p->height + Q2_STEP-1)/Q2_STEP));
-     for(y=0; y<p->height; y++){
-         for(x=0; x<p->width; x++){
-             int sx= (x-xo + step/2) / step / Q2_STEP;
-             int sy= (y-yo + step/2) / step / Q2_STEP;
-             int v= r0[x + y*p->width] - r1[x + y*p->width];
-             assert(sx>=0 && sy>=0 && sx < score_stride);
-             v= ((v+8)>>4)<<4;
-             score[sx + sy*score_stride] += v*v;
-             assert(score[sx + sy*score_stride] >= 0);
-         }
-     }
- }
- static void dequantize_all(SnowContext *s, Plane *p, IDWTELEM *buffer, int width, int height){
-     int level, orientation;
-     for(level=0; level<s->spatial_decomposition_count; level++){
-         for(orientation=level ? 1 : 0; orientation<4; orientation++){
-             SubBand *b= &p->band[level][orientation];
-             IDWTELEM *dst= buffer + (b->ibuf - s->spatial_idwt_buffer);
-             dequantize(s, b, dst, b->stride);
-         }
-     }
- }
- static void dwt_quantize(SnowContext *s, Plane *p, DWTELEM *buffer, int width, int height, int stride, int type){
-     int level, orientation, ys, xs, x, y, pass;
-     IDWTELEM best_dequant[height * stride];
-     IDWTELEM idwt2_buffer[height * stride];
-     const int score_stride= (width + 10)/Q2_STEP;
-     int best_score[(width + 10)/Q2_STEP * (height + 10)/Q2_STEP]; //FIXME size
-     int score[(width + 10)/Q2_STEP * (height + 10)/Q2_STEP]; //FIXME size
-     int threshold= (s->m.lambda * s->m.lambda) >> 6;
-     //FIXME pass the copy cleanly ?
- //    memcpy(dwt_buffer, buffer, height * stride * sizeof(DWTELEM));
-     ff_spatial_dwt(buffer, width, height, stride, type, s->spatial_decomposition_count);
-     for(level=0; level<s->spatial_decomposition_count; level++){
-         for(orientation=level ? 1 : 0; orientation<4; orientation++){
-             SubBand *b= &p->band[level][orientation];
-             IDWTELEM *dst= best_dequant + (b->ibuf - s->spatial_idwt_buffer);
-              DWTELEM *src=       buffer + (b-> buf - s->spatial_dwt_buffer);
-             assert(src == b->buf); // code does not depend on this but it is true currently
-             quantize(s, b, dst, src, b->stride, s->qbias);
-         }
-     }
-     for(pass=0; pass<1; pass++){
-         if(s->qbias == 0) //keyframe
-             continue;
-         for(level=0; level<s->spatial_decomposition_count; level++){
-             for(orientation=level ? 1 : 0; orientation<4; orientation++){
-                 SubBand *b= &p->band[level][orientation];
-                 IDWTELEM *dst= idwt2_buffer + (b->ibuf - s->spatial_idwt_buffer);
-                 IDWTELEM *best_dst= best_dequant + (b->ibuf - s->spatial_idwt_buffer);
-                 for(ys= 0; ys<Q2_STEP; ys++){
-                     for(xs= 0; xs<Q2_STEP; xs++){
-                         memcpy(idwt2_buffer, best_dequant, height * stride * sizeof(IDWTELEM));
-                         dequantize_all(s, p, idwt2_buffer, width, height);
-                         ff_spatial_idwt(idwt2_buffer, width, height, stride, type, s->spatial_decomposition_count);
-                         find_sse(s, p, best_score, score_stride, idwt2_buffer, s->spatial_idwt_buffer, level, orientation);
-                         memcpy(idwt2_buffer, best_dequant, height * stride * sizeof(IDWTELEM));
-                         for(y=ys; y<b->height; y+= Q2_STEP){
-                             for(x=xs; x<b->width; x+= Q2_STEP){
-                                 if(dst[x + y*b->stride]<0) dst[x + y*b->stride]++;
-                                 if(dst[x + y*b->stride]>0) dst[x + y*b->stride]--;
-                                 //FIXME try more than just --
-                             }
-                         }
-                         dequantize_all(s, p, idwt2_buffer, width, height);
-                         ff_spatial_idwt(idwt2_buffer, width, height, stride, type, s->spatial_decomposition_count);
-                         find_sse(s, p, score, score_stride, idwt2_buffer, s->spatial_idwt_buffer, level, orientation);
-                         for(y=ys; y<b->height; y+= Q2_STEP){
-                             for(x=xs; x<b->width; x+= Q2_STEP){
-                                 int score_idx= x/Q2_STEP + (y/Q2_STEP)*score_stride;
-                                 if(score[score_idx] <= best_score[score_idx] + threshold){
-                                     best_score[score_idx]= score[score_idx];
-                                     if(best_dst[x + y*b->stride]<0) best_dst[x + y*b->stride]++;
-                                     if(best_dst[x + y*b->stride]>0) best_dst[x + y*b->stride]--;
-                                     //FIXME copy instead
-                                 }
-                             }
-                         }
-                     }
-                 }
-             }
-         }
-     }
-     memcpy(s->spatial_idwt_buffer, best_dequant, height * stride * sizeof(IDWTELEM)); //FIXME work with that directly instead of copy at the end
- }
- #endif /* QUANTIZE2==1 */
  #define USE_HALFPEL_PLANE 0
  
  static void halfpel_interpol(SnowContext *s, uint8_t *halfpel[4][4], AVFrame *frame){
      }
  }
  
- static void release_buffer(AVCodecContext *avctx){
+ void ff_snow_release_buffer(AVCodecContext *avctx)
+ {
      SnowContext *s = avctx->priv_data;
      int i;
  
      }
  }
  
static int frame_start(SnowContext *s){
int ff_snow_frame_start(SnowContext *s){
     AVFrame tmp;
     int w= s->avctx->width; //FIXME round up to x16 ?
     int h= s->avctx->height;
                            EDGE_WIDTH/2, EDGE_WIDTH/2, EDGE_TOP | EDGE_BOTTOM);
      }
  
-     release_buffer(s->avctx);
+     ff_snow_release_buffer(s->avctx);
  
      tmp= s->last_picture[s->max_ref_frames-1];
      memmove(s->last_picture+1, s->last_picture, (s->max_ref_frames-1)*sizeof(AVFrame));
          }
      }
  
 -    s->current_picture.reference= 1;
 +    s->current_picture.reference= 3;
      if(s->avctx->get_buffer(s->avctx, &s->current_picture) < 0){
          av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed\n");
          return -1;
      return 0;
  }
  
- static av_cold void common_end(SnowContext *s){
+ av_cold void ff_snow_common_end(SnowContext *s)
+ {
      int plane_index, level, orientation, i;
  
      av_freep(&s->spatial_dwt_buffer);
          s->avctx->release_buffer(s->avctx, &s->current_picture);
  }
  
- static av_cold int decode_init(AVCodecContext *avctx)
- {
-     avctx->pix_fmt= PIX_FMT_YUV420P;
-     common_init(avctx);
-     return 0;
- }
- static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, 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;
-     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(decode_header(s)<0)
-         return -1;
-     common_init_after_header(avctx);
-     // realloc slice buffer for the case that spatial_decomposition_count changed
-     ff_slice_buffer_destroy(&s->sb);
-     ff_slice_buffer_init(&s->sb, s->plane[0].height, (MB_SIZE >> s->block_max_depth) + s->spatial_decomposition_count * 8 + 1, s->plane[0].width, s->spatial_idwt_buffer);
-     for(plane_index=0; plane_index<3; 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;
-     }
-     alloc_blocks(s);
-     if(frame_start(s) < 0)
-         return -1;
-     //keyframe flag duplication mess FIXME
-     if(avctx->debug&FF_DEBUG_PICT_INFO)
-         av_log(avctx, AV_LOG_ERROR, "keyframe:%d qlog:%d\n", s->keyframe, s->qlog);
-     decode_blocks(s);
-     for(plane_index=0; plane_index<3; 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_w    = plane_index ? block_size/2 : 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_w*mb_y;
-             int slice_h = block_w*(mb_y+1);
-             if (!(s->keyframe || s->avctx->debug&512)){
-                 slice_starty = FFMAX(0, slice_starty - (block_w >> 1));
-                 slice_h -= (block_w >> 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_w * our_mb_start) >> (s->spatial_decomposition_count - level)) + s->spatial_decomposition_count - level + extra: 0);
-                     end_y = (((block_w * 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_w >> (1+s->spatial_decomposition_count - level)));
-                         end_y = FFMAX(0, end_y - (block_w >> (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, 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();
-     release_buffer(avctx);
-     if(!(s->avctx->debug&2048))
-         *picture= s->current_picture;
-     else
-         *picture= s->mconly_picture;
-     *data_size = sizeof(AVFrame);
-     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);
-     common_end(s);
-     return 0;
- }
- AVCodec ff_snow_decoder = {
-     .name           = "snow",
-     .type           = AVMEDIA_TYPE_VIDEO,
-     .id             = 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*/,
-     .long_name = NULL_IF_CONFIG_SMALL("Snow"),
- };
- #if CONFIG_SNOW_ENCODER
- static av_cold int encode_init(AVCodecContext *avctx)
- {
-     SnowContext *s = avctx->priv_data;
-     int plane_index;
-     if(avctx->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL){
-         av_log(avctx, AV_LOG_ERROR, "This codec is under development, files encoded with it may not be decodable with future versions!!!\n"
-                "Use vstrict=-2 / -strict -2 to use it anyway.\n");
-         return -1;
-     }
-     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;
-     }
-     common_init(avctx);
-     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((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));
-     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->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));
-     avctx->coded_frame= &s->current_picture;
-     switch(avctx->pix_fmt){
- //    case PIX_FMT_YUV444P:
- //    case PIX_FMT_YUV422P:
-     case PIX_FMT_YUV420P:
-     case PIX_FMT_GRAY8:
- //    case PIX_FMT_YUV411P:
- //    case PIX_FMT_YUV410P:
-         s->colorspace_type= 0;
-         break;
- /*    case 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);
-     s->chroma_h_shift= 1;
-     s->chroma_v_shift= 1;
-     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);
-     s->avctx->get_buffer(s->avctx, &s->input_picture);
-     if(s->avctx->me_method == ME_ITER){
-         int i;
-         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(size*sizeof(int16_t[2]));
-             s->ref_scores[i]= av_mallocz(size*sizeof(uint32_t));
-         }
-     }
-     return 0;
- }
- //near copy & paste from dsputil, FIXME
- static int pix_sum(uint8_t * pix, int line_size, int w)
- {
-     int s, i, j;
-     s = 0;
-     for (i = 0; i < w; 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_squareTbl + 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;
- }
- //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 + y*uvstride)*block_w/2,
-                                 s->input_picture.data[2] + (x + y*uvstride)*block_w/2};
-     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;
-     assert(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;
-     assert(c->  stride ==   stride);
-     assert(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);
-         assert(ref_mx >= c->xmin);
-         assert(ref_mx <= c->xmax);
-         assert(ref_my >= c->ymin);
-         assert(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);
-     l= (sum + block_s/2)/block_s;
-     iscore = pix_norm1(current_data[0], stride, block_w) - 2*l*sum + l*l*block_s;
-     block_s= block_w*block_w>>2;
-     sum = pix_sum(current_data[1], uvstride, block_w>>1);
-     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>>1);
-     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;
-     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);
-     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);
-     assert(iscore < 255*255*256 + s->lambda2*10);
-     assert(iscore >= 0);
-     assert(l>=0 && l<=255);
-     assert(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);
-         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/2 : block_size;
-     const uint8_t *obmc  = plane_index ? obmc_tab[s->block_max_depth+1] : obmc_tab[s->block_max_depth];
-     const int obmc_stride= plane_index ? block_size : 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;
-     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_w*mb_y2 + block_w/2;
-         add_yblock(s, 0, NULL, dst + ((i&1)+(i>>1)*obmc_stride)*block_w, NULL, obmc,
-                     x, y, block_w, block_w, 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_w); 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_w*mb_y - block_w/2))*obmc_stride;
-                 int obmc_v= obmc[index];
-                 int d;
-                 if(y<0) obmc_v += obmc[index + block_w*obmc_stride];
-                 if(x<0) obmc_v += obmc[index + block_w];
-                 if(y+block_w>h) obmc_v += obmc[index - block_w*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(((ab<<LOG2_OBMC_MAX) + aa/2)/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, const uint8_t *obmc_edged){
-     Plane *p= &s->plane[plane_index];
-     const int block_size = MB_SIZE >> s->block_max_depth;
-     const int block_w    = plane_index ? block_size/2 : block_size;
-     const int obmc_stride= plane_index ? block_size : 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[ref_stride*(2*MB_SIZE+HTAPS_MAX-1)];
-     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_w*mb_y - block_w/2;
-     int x0= FFMAX(0,-sx);
-     int y0= FFMAX(0,-sy);
-     int x1= FFMIN(block_w*2, w-sx);
-     int y1= FFMIN(block_w*2, h-sy);
-     int i,x,y;
-     pred_block(s, cur, tmp, ref_stride, sx, sy, block_w*2, block_w*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*obmc_stride;
-         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_w;
-         else
-             y0 = block_w;
-         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 + off, dst + off, ref_stride, 16);
-             }
-         }
-     }else{
-         assert(block_w==8);
-         distortion = s->dsp.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/2 : block_size;
-     const uint8_t *obmc  = plane_index ? obmc_tab[s->block_max_depth+1] : obmc_tab[s->block_max_depth];
-     const int obmc_stride= plane_index ? block_size : 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);
-     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_w*mb_y2 + block_w/2;
-         add_yblock(s, 0, NULL, zero_dst, dst, obmc,
-                    x, y, block_w, block_w, 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_w; y2++)
-             memcpy(dst + x + y2*ref_stride, src + x + y2*ref_stride, block_w);
-         if(x<0){
-             for(y2= y; y2<y+block_w; y2++)
-                 memcpy(dst + x + y2*ref_stride, src + x + y2*ref_stride, -x);
-         }
-         if(x+block_w > w){
-             for(y2= y; y2<y+block_w; y2++)
-                 memcpy(dst + w + y2*ref_stride, src + w + y2*ref_stride, x+block_w - w);
-         }
-         assert(block_w== 8 || block_w==16);
-         distortion += s->dsp.me_cmp[block_w==8](&s->m, src + x + y*ref_stride, dst + x + y*ref_stride, ref_stride, block_w);
-     }
-     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, IDWTELEM *src, 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[w*h];
-         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);
-                         assert(v);
-                     }else{
-                         run--;
-                         assert(!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 + quant3bA[l2&0xFF] + 3*quant3bA[t2&0xFF]], v<0);
-                 }
-             }
-         }
-     }
-     return 0;
- }
- static int encode_subband(SnowContext *s, SubBand *b, IDWTELEM *src, 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, const uint8_t *obmc_edged, 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;
-     int rd, index, value;
-     assert(mb_x>=0 && mb_y>=0);
-     assert(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, const uint8_t *obmc_edged, 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]= {block[0], block[1], block[b_stride], block[b_stride+1]};
-     int rd, index, value;
-     assert(mb_x>=0 && mb_y>=0);
-     assert(mb_x<b_stride);
-     assert(((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[b_w*2][b_w*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;
-                     memcpy(obmc_edged, obmc_tab[s->block_max_depth], b_w*b_w*4);
-                     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 sx= block_w*mb_x - block_w/2;
-                     const int sy= block_w*mb_y - block_w/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_w*2; y++)
-                         memcpy(dst + sx + y*stride, src + sx + y*stride, block_w*2);
-                     if(sx<0){
-                         for(y=sy; y<sy+block_w*2; y++)
-                             memcpy(dst + sx + y*stride, src + sx + y*stride, -sx);
-                     }
-                     if(sx+block_w*2 > w){
-                         for(y=sy; y<sy+block_w*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<3; 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= 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= 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<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){
-         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);
-         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<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<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*log(qscale / (float)FF_QP2LAMBDA)/log(2))
-            + 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= 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 */
-     coef_sum = (uint64_t)coef_sum * coef_sum >> 16;
-     assert(coef_sum < INT_MAX);
-     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, width, height, width, s->spatial_decomposition_type, s->spatial_decomposition_count);
-             for(y=0; y<height; y++){
-                 for(x=0; x<width; x++){
-                     int64_t d= s->spatial_idwt_buffer[x + y*width]*16;
-                     error += d*d;
-                 }
-             }
-             b->qlog= (int)(log(352256.0/sqrt(error)) / log(pow(2.0, 1.0/QROOT))+0.5);
-         }
-     }
- }
- static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, void *data){
-     SnowContext *s = avctx->priv_data;
-     RangeCoder * const c= &s->c;
-     AVFrame *pict = data;
-     const int width= s->avctx->width;
-     const int height= s->avctx->height;
-     int level, orientation, plane_index, i, y;
-     uint8_t rc_header_bak[sizeof(s->header_state)];
-     uint8_t rc_block_bak[sizeof(s->block_state)];
-     ff_init_range_encoder(c, buf, buf_size);
-     ff_build_rac_states(c, 0.05*(1LL<<32), 256-8);
-     for(i=0; i<3; i++){
-         int shift= !!i;
-         for(y=0; y<(height>>shift); y++)
-             memcpy(&s->input_picture.data[i][y * s->input_picture.linesize[i]],
-                    &pict->data[i][y * pict->linesize[i]],
-                    width>>shift);
-     }
-     s->new_picture = *pict;
-     s->m.picture_number= avctx->frame_number;
-     if(avctx->flags&CODEC_FLAG_PASS2){
-         s->m.pict_type =
-         pict->pict_type= s->m.rc_context.entry[avctx->frame_number].new_pict_type;
-         s->keyframe= pict->pict_type==AV_PICTURE_TYPE_I;
-         if(!(avctx->flags&CODEC_FLAG_QSCALE)) {
-             pict->quality= ff_rate_estimate_qscale(&s->m, 0);
-             if (pict->quality < 0)
-                 return -1;
-         }
-     }else{
-         s->keyframe= avctx->gop_size==0 || avctx->frame_number % avctx->gop_size == 0;
-         s->m.pict_type=
-         pict->pict_type= s->keyframe ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P;
-     }
-     if(s->pass1_rc && avctx->frame_number == 0)
-         pict->quality= 2*FF_QP2LAMBDA;
-     if(pict->quality){
-         s->qlog= qscale2qlog(pict->quality);
-         s->lambda = pict->quality * 3/2;
-     }
-     if(s->qlog < 0 || (!pict->quality && (avctx->flags & CODEC_FLAG_QSCALE))){
-         s->qlog= LOSSLESS_QLOG;
-         s->lambda = 0;
-     }//else keep previous frame's qlog until after motion estimation
-     frame_start(s);
-     s->m.current_picture_ptr= &s->m.current_picture;
-     s->m.last_picture.f.pts = s->m.current_picture.f.pts;
-     s->m.current_picture.f.pts = pict->pts;
-     if(pict->pict_type == AV_PICTURE_TYPE_P){
-         int block_width = (width +15)>>4;
-         int block_height= (height+15)>>4;
-         int stride= s->current_picture.linesize[0];
-         assert(s->current_picture.data[0]);
-         assert(s->last_picture[0].data[0]);
-         s->m.avctx= s->avctx;
-         s->m.current_picture.f.data[0] = s->current_picture.data[0];
-         s->m.   last_picture.f.data[0] = s->last_picture[0].data[0];
-         s->m.    new_picture.f.data[0] = s->  input_picture.data[0];
-         s->m.   last_picture_ptr= &s->m.   last_picture;
-         s->m.linesize=
-         s->m.   last_picture.f.linesize[0] =
-         s->m.    new_picture.f.linesize[0] =
-         s->m.current_picture.f.linesize[0] = stride;
-         s->m.uvlinesize= s->current_picture.linesize[1];
-         s->m.width = width;
-         s->m.height= height;
-         s->m.mb_width = block_width;
-         s->m.mb_height= block_height;
-         s->m.mb_stride=   s->m.mb_width+1;
-         s->m.b8_stride= 2*s->m.mb_width+1;
-         s->m.f_code=1;
-         s->m.pict_type= pict->pict_type;
-         s->m.me_method= s->avctx->me_method;
-         s->m.me.scene_change_score=0;
-         s->m.flags= s->avctx->flags;
-         s->m.quarter_sample= (s->avctx->flags & CODEC_FLAG_QPEL)!=0;
-         s->m.out_format= FMT_H263;
-         s->m.unrestricted_mv= 1;
-         s->m.lambda = s->lambda;
-         s->m.qscale= (s->m.lambda*139 + FF_LAMBDA_SCALE*64) >> (FF_LAMBDA_SHIFT + 7);
-         s->lambda2= s->m.lambda2= (s->m.lambda*s->m.lambda + FF_LAMBDA_SCALE/2) >> FF_LAMBDA_SHIFT;
-         s->m.dsp= s->dsp; //move
-         ff_init_me(&s->m);
-         s->dsp= s->m.dsp;
-     }
-     if(s->pass1_rc){
-         memcpy(rc_header_bak, s->header_state, sizeof(s->header_state));
-         memcpy(rc_block_bak, s->block_state, sizeof(s->block_state));
-     }
- redo_frame:
-     if(pict->pict_type == AV_PICTURE_TYPE_I)
-         s->spatial_decomposition_count= 5;
-     else
-         s->spatial_decomposition_count= 5;
-     s->m.pict_type = pict->pict_type;
-     s->qbias= pict->pict_type == AV_PICTURE_TYPE_P ? 2 : 0;
-     common_init_after_header(avctx);
-     if(s->last_spatial_decomposition_count != s->spatial_decomposition_count){
-         for(plane_index=0; plane_index<3; plane_index++){
-             calculate_visual_weight(s, &s->plane[plane_index]);
-         }
-     }
-     encode_header(s);
-     s->m.misc_bits = 8*(s->c.bytestream - s->c.bytestream_start);
-     encode_blocks(s, 1);
-     s->m.mv_bits = 8*(s->c.bytestream - s->c.bytestream_start) - s->m.misc_bits;
-     for(plane_index=0; plane_index<3; plane_index++){
-         Plane *p= &s->plane[plane_index];
-         int w= p->width;
-         int h= p->height;
-         int x, y;
- //        int bits= put_bits_count(&s->c.pb);
-         if (!s->memc_only) {
-             //FIXME optimize
-             if(pict->data[plane_index]) //FIXME gray hack
-                 for(y=0; y<h; y++){
-                     for(x=0; x<w; x++){
-                         s->spatial_idwt_buffer[y*w + x]= pict->data[plane_index][y*pict->linesize[plane_index] + x]<<FRAC_BITS;
-                     }
-                 }
-             predict_plane(s, s->spatial_idwt_buffer, plane_index, 0);
-             if(   plane_index==0
-                && pict->pict_type == AV_PICTURE_TYPE_P
-                && !(avctx->flags&CODEC_FLAG_PASS2)
-                && s->m.me.scene_change_score > s->avctx->scenechange_threshold){
-                 ff_init_range_encoder(c, buf, buf_size);
-                 ff_build_rac_states(c, 0.05*(1LL<<32), 256-8);
-                 pict->pict_type= AV_PICTURE_TYPE_I;
-                 s->keyframe=1;
-                 s->current_picture.key_frame=1;
-                 goto redo_frame;
-             }
-             if(s->qlog == LOSSLESS_QLOG){
-                 for(y=0; y<h; y++){
-                     for(x=0; x<w; x++){
-                         s->spatial_dwt_buffer[y*w + x]= (s->spatial_idwt_buffer[y*w + x] + (1<<(FRAC_BITS-1))-1)>>FRAC_BITS;
-                     }
-                 }
-             }else{
-                 for(y=0; y<h; y++){
-                     for(x=0; x<w; x++){
-                         s->spatial_dwt_buffer[y*w + x]=s->spatial_idwt_buffer[y*w + x]<<ENCODER_EXTRA_BITS;
-                     }
-                 }
-             }
-             /*  if(QUANTIZE2)
-                 dwt_quantize(s, p, s->spatial_dwt_buffer, w, h, w, s->spatial_decomposition_type);
-             else*/
-                 ff_spatial_dwt(s->spatial_dwt_buffer, w, h, w, s->spatial_decomposition_type, s->spatial_decomposition_count);
-             if(s->pass1_rc && plane_index==0){
-                 int delta_qlog = ratecontrol_1pass(s, pict);
-                 if (delta_qlog <= INT_MIN)
-                     return -1;
-                 if(delta_qlog){
-                     //reordering qlog in the bitstream would eliminate this reset
-                     ff_init_range_encoder(c, buf, buf_size);
-                     memcpy(s->header_state, rc_header_bak, sizeof(s->header_state));
-                     memcpy(s->block_state, rc_block_bak, sizeof(s->block_state));
-                     encode_header(s);
-                     encode_blocks(s, 0);
-                 }
-             }
-             for(level=0; level<s->spatial_decomposition_count; level++){
-                 for(orientation=level ? 1 : 0; orientation<4; orientation++){
-                     SubBand *b= &p->band[level][orientation];
-                     if(!QUANTIZE2)
-                         quantize(s, b, b->ibuf, b->buf, b->stride, s->qbias);
-                     if(orientation==0)
-                         decorrelate(s, b, b->ibuf, b->stride, pict->pict_type == AV_PICTURE_TYPE_P, 0);
-                     encode_subband(s, b, b->ibuf, b->parent ? b->parent->ibuf : NULL, b->stride, orientation);
-                     assert(b->parent==NULL || b->parent->stride == b->stride*2);
-                     if(orientation==0)
-                         correlate(s, b, b->ibuf, b->stride, 1, 0);
-                 }
-             }
-             for(level=0; level<s->spatial_decomposition_count; level++){
-                 for(orientation=level ? 1 : 0; orientation<4; orientation++){
-                     SubBand *b= &p->band[level][orientation];
-                     dequantize(s, b, b->ibuf, b->stride);
-                 }
-             }
-             ff_spatial_idwt(s->spatial_idwt_buffer, w, h, w, s->spatial_decomposition_type, s->spatial_decomposition_count);
-             if(s->qlog == LOSSLESS_QLOG){
-                 for(y=0; y<h; y++){
-                     for(x=0; x<w; x++){
-                         s->spatial_idwt_buffer[y*w + x]<<=FRAC_BITS;
-                     }
-                 }
-             }
-             predict_plane(s, s->spatial_idwt_buffer, plane_index, 1);
-         }else{
-             //ME/MC only
-             if(pict->pict_type == AV_PICTURE_TYPE_I){
-                 for(y=0; y<h; y++){
-                     for(x=0; x<w; x++){
-                         s->current_picture.data[plane_index][y*s->current_picture.linesize[plane_index] + x]=
-                             pict->data[plane_index][y*pict->linesize[plane_index] + x];
-                     }
-                 }
-             }else{
-                 memset(s->spatial_idwt_buffer, 0, sizeof(IDWTELEM)*w*h);
-                 predict_plane(s, s->spatial_idwt_buffer, plane_index, 1);
-             }
-         }
-         if(s->avctx->flags&CODEC_FLAG_PSNR){
-             int64_t error= 0;
-             if(pict->data[plane_index]) //FIXME gray hack
-                 for(y=0; y<h; y++){
-                     for(x=0; x<w; x++){
-                         int d= s->current_picture.data[plane_index][y*s->current_picture.linesize[plane_index] + x] - pict->data[plane_index][y*pict->linesize[plane_index] + x];
-                         error += d*d;
-                     }
-                 }
-             s->avctx->error[plane_index] += error;
-             s->current_picture.error[plane_index] = error;
-         }
-     }
-     update_last_header_values(s);
-     release_buffer(avctx);
-     s->current_picture.coded_picture_number = avctx->frame_number;
-     s->current_picture.pict_type = pict->pict_type;
-     s->current_picture.quality = pict->quality;
-     s->m.frame_bits = 8*(s->c.bytestream - s->c.bytestream_start);
-     s->m.p_tex_bits = s->m.frame_bits - s->m.misc_bits - s->m.mv_bits;
-     s->m.current_picture.f.display_picture_number =
-     s->m.current_picture.f.coded_picture_number   = avctx->frame_number;
-     s->m.current_picture.f.quality                = pict->quality;
-     s->m.total_bits += 8*(s->c.bytestream - s->c.bytestream_start);
-     if(s->pass1_rc)
-         if (ff_rate_estimate_qscale(&s->m, 0) < 0)
-             return -1;
-     if(avctx->flags&CODEC_FLAG_PASS1)
-         ff_write_pass1_stats(&s->m);
-     s->m.last_pict_type = s->m.pict_type;
-     avctx->frame_bits = s->m.frame_bits;
-     avctx->mv_bits = s->m.mv_bits;
-     avctx->misc_bits = s->m.misc_bits;
-     avctx->p_tex_bits = s->m.p_tex_bits;
-     emms_c();
-     return ff_rac_terminate(c);
- }
- static av_cold int encode_end(AVCodecContext *avctx)
- {
-     SnowContext *s = avctx->priv_data;
-     common_end(s);
-     if (s->input_picture.data[0])
-         avctx->release_buffer(avctx, &s->input_picture);
-     av_free(avctx->stats_out);
-     return 0;
- }
- #define OFFSET(x) offsetof(SnowContext, x)
- #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
- static const AVOption options[] = {
-     { "memc_only",      "Only do ME/MC (I frames -> ref, P frame -> ME+MC).",   OFFSET(memc_only), AV_OPT_TYPE_INT, { 0 }, 0, 1, VE },
-     { NULL },
- };
- static const AVClass snowenc_class = {
-     .class_name = "snow encoder",
-     .item_name  = av_default_item_name,
-     .option     = options,
-     .version    = LIBAVUTIL_VERSION_INT,
- };
- AVCodec ff_snow_encoder = {
-     .name           = "snow",
-     .type           = AVMEDIA_TYPE_VIDEO,
-     .id             = CODEC_ID_SNOW,
-     .priv_data_size = sizeof(SnowContext),
-     .init           = encode_init,
-     .encode         = encode_frame,
-     .close          = encode_end,
-     .long_name = NULL_IF_CONFIG_SMALL("Snow"),
-     .priv_class     = &snowenc_class,
- };
- #endif
- #ifdef TEST
- #undef malloc
- #undef free
- #undef printf
- #include "libavutil/lfg.h"
- #include "libavutil/mathematics.h"
- int main(void){
-     int width=256;
-     int height=256;
-     int buffer[2][width*height];
-     SnowContext s;
-     int i;
-     AVLFG prng;
-     s.spatial_decomposition_count=6;
-     s.spatial_decomposition_type=1;
-     av_lfg_init(&prng, 1);
-     printf("testing 5/3 DWT\n");
-     for(i=0; i<width*height; i++)
-         buffer[0][i] = buffer[1][i] = av_lfg_get(&prng) % 54321 - 12345;
-     ff_spatial_dwt(buffer[0], width, height, width, s.spatial_decomposition_type, s.spatial_decomposition_count);
-     ff_spatial_idwt(buffer[0], width, height, width, s.spatial_decomposition_type, s.spatial_decomposition_count);
-     for(i=0; i<width*height; i++)
-         if(buffer[0][i]!= buffer[1][i]) printf("fsck: %6d %12d %7d\n",i, buffer[0][i], buffer[1][i]);
-     printf("testing 9/7 DWT\n");
-     s.spatial_decomposition_type=0;
-     for(i=0; i<width*height; i++)
-         buffer[0][i] = buffer[1][i] = av_lfg_get(&prng) % 54321 - 12345;
-     ff_spatial_dwt(buffer[0], width, height, width, s.spatial_decomposition_type, s.spatial_decomposition_count);
-     ff_spatial_idwt(buffer[0], width, height, width, s.spatial_decomposition_type, s.spatial_decomposition_count);
-     for(i=0; i<width*height; i++)
-         if(FFABS(buffer[0][i] - buffer[1][i])>20) printf("fsck: %6d %12d %7d\n",i, buffer[0][i], buffer[1][i]);
-     {
-     int level, orientation, x, y;
-     int64_t errors[8][4];
-     int64_t g=0;
-         memset(errors, 0, sizeof(errors));
-         s.spatial_decomposition_count=3;
-         s.spatial_decomposition_type=0;
-         for(level=0; level<s.spatial_decomposition_count; level++){
-             for(orientation=level ? 1 : 0; orientation<4; orientation++){
-                 int w= width  >> (s.spatial_decomposition_count-level);
-                 int h= height >> (s.spatial_decomposition_count-level);
-                 int stride= width  << (s.spatial_decomposition_count-level);
-                 DWTELEM *buf= buffer[0];
-                 int64_t error=0;
-                 if(orientation&1) buf+=w;
-                 if(orientation>1) buf+=stride>>1;
-                 memset(buffer[0], 0, sizeof(int)*width*height);
-                 buf[w/2 + h/2*stride]= 256*256;
-                 ff_spatial_idwt(buffer[0], width, height, width, s.spatial_decomposition_type, s.spatial_decomposition_count);
-                 for(y=0; y<height; y++){
-                     for(x=0; x<width; x++){
-                         int64_t d= buffer[0][x + y*width];
-                         error += d*d;
-                         if(FFABS(width/2-x)<9 && FFABS(height/2-y)<9 && level==2) printf("%8"PRId64" ", d);
-                     }
-                     if(FFABS(height/2-y)<9 && level==2) printf("\n");
-                 }
-                 error= (int)(sqrt(error)+0.5);
-                 errors[level][orientation]= error;
-                 if(g) g=av_gcd(g, error);
-                 else g= error;
-             }
-         }
-         printf("static int const visual_weight[][4]={\n");
-         for(level=0; level<s.spatial_decomposition_count; level++){
-             printf("  {");
-             for(orientation=0; orientation<4; orientation++){
-                 printf("%8"PRId64",", errors[level][orientation]/g);
-             }
-             printf("},\n");
-         }
-         printf("};\n");
-         {
-             int level=2;
-             int w= width  >> (s.spatial_decomposition_count-level);
-             //int h= height >> (s.spatial_decomposition_count-level);
-             int stride= width  << (s.spatial_decomposition_count-level);
-             DWTELEM *buf= buffer[0];
-             int64_t error=0;
-             buf+=w;
-             buf+=stride>>1;
-             memset(buffer[0], 0, sizeof(int)*width*height);
-             for(y=0; y<height; y++){
-                 for(x=0; x<width; x++){
-                     int tab[4]={0,2,3,1};
-                     buffer[0][x+width*y]= 256*256*tab[(x&1) + 2*(y&1)];
-                 }
-             }
-             ff_spatial_dwt(buffer[0], width, height, width, s.spatial_decomposition_type, s.spatial_decomposition_count);
-             for(y=0; y<height; y++){
-                 for(x=0; x<width; x++){
-                     int64_t d= buffer[0][x + y*width];
-                     error += d*d;
-                     if(FFABS(width/2-x)<9 && FFABS(height/2-y)<9) printf("%8"PRId64" ", d);
-                 }
-                 if(FFABS(height/2-y)<9) printf("\n");
-             }
-         }
-     }
-     return 0;
- }
- #endif /* TEST */
diff --combined libavcodec/snow.h
index 7d847e4b37f1a5d17187e0dba260cebcd0cade39,f43deb1d728cebfc37c8b24ee18fb05c24494d91..b1589ca52e7b71681bc883c6553664c29bd9e003
@@@ -2,20 -2,20 +2,20 @@@
   * Copyright (C) 2004 Michael Niedermayer <michaelni@gmx.at>
   * Copyright (C) 2006 Robert Edele <yartrebo@earthlink.net>
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * FFmpeg is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 2.1 of the License, or (at your option) any later version.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * FFmpeg is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
 - * License along with Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
  #include "dsputil.h"
  #include "dwt.h"
  
+ #include "rangecoder.h"
+ #include "mathops.h"
+ #include "mpegvideo.h"
  #define MID_STATE 128
  
  #define MAX_PLANES 4
  
  #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;
+     DSPContext dsp;
+     DWTContext 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;
+     IDWTELEM *spatial_idwt_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;
+     Plane plane[MAX_PLANES];
+     BlockNode *block;
+ #define ME_CACHE_SIZE 1024
+     int me_cache[ME_CACHE_SIZE];
+     int me_cache_generation;
+     slice_buffer sb;
+     int memc_only;
+     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;
+ }SnowContext;
+ /* Tables */
+ extern const uint8_t * const obmc_tab[4];
+ #ifdef __sgi
+ // Avoid a name clash on SGI IRIX
+ #undef qexp
+ #endif
+ extern uint8_t qexp[QROOT];
+ extern int scale_mv_ref[MAX_REF_FRAMES][MAX_REF_FRAMES];
  
  /* C bits used by mmx/sse2/altivec */
  
@@@ -75,4 -211,482 +211,482 @@@ static av_always_inline void snow_horiz
          }
  }
  
+ /* 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, int stride,
+                      int sx, int sy, int b_w, int b_h, BlockNode *block,
+                      int plane_index, int w, int h);
+ /* 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 = 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;
+     }else 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;
+     }else if(src_y + b_h> h){
+         b_h = h - src_y;
+     }
+     if(b_w<=0 || b_h<=0) return;
+     assert(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/2 : block_size;
+     const uint8_t *obmc  = plane_index ? obmc_tab[s->block_max_depth+1] : obmc_tab[s->block_max_depth];
+     const int obmc_stride= plane_index ? block_size : 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_w*mb_y; y<FFMIN(h,block_w*(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_w*mb_y; y<FFMIN(h,block_w*(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_w*mb_y - block_w/2,
+                    block_w, block_w,
+                    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;
+     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 init_ref(MotionEstContext *c, uint8_t *src[3], uint8_t *ref[3], uint8_t *ref2[3], int x, int y, int ref_index){
+     const int offset[3]= {
+           y*c->  stride + x,
+         ((y*c->uvstride + x)>>1),
+         ((y*c->uvstride + x)>>1),
+     };
+     int i;
+     for(i=0; i<3; i++){
+         c->src[0][i]= src [i];
+         c->ref[0][i]= ref [i] + offset[i];
+     }
+     assert(!ref_index);
+ }
+ /* bitstream functions */
+ extern const int8_t 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;
+     assert(v>=0);
+     assert(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;
+     assert(log2>=-4);
+     while(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 + quant3bA[l&0xFF] + 3*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;
+                     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);
+                     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 */
diff --combined libavcodec/snowdec.c
index 0000000000000000000000000000000000000000,2b6f6e11c7a12f467b3307bc228d3b7fb6ff0702..9fd25a5335e55cee77f26f1e78dc343a7e72cdbc
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,546 +1,546 @@@
 - * This file is part of Libav.
+ /*
+  * Copyright (C) 2004 Michael Niedermayer <michaelni@gmx.at>
+  *
 - * Libav is free software; you can redistribute it and/or
++ * This file is part of FFmpeg.
+  *
 - * Libav is distributed in the hope that it will be useful,
++ * FFmpeg is free software; you can redistribute it and/or
+  * modify it under the terms of the GNU Lesser General Public
+  * License as published by the Free Software Foundation; either
+  * version 2.1 of the License, or (at your option) any later version.
+  *
 - * License along with Libav; if not, write to the Free Software
++ * FFmpeg is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  * Lesser General Public License for more details.
+  *
+  * You should have received a copy of the GNU Lesser General Public
++ * 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 "dsputil.h"
+ #include "dwt.h"
+ #include "snow.h"
+ #include "rangecoder.h"
+ #include "mathops.h"
+ #include "mpegvideo.h"
+ #include "h263.h"
+ #undef NDEBUG
+ #include <assert.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/2 : block_size;
+     const uint8_t *obmc  = plane_index ? obmc_tab[s->block_max_depth+1] : obmc_tab[s->block_max_depth];
+     int obmc_stride= plane_index ? block_size : 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_w*mb_y; y<FFMIN(h,block_w*(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_w*mb_y; y<FFMIN(h,block_w*(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_w*mb_y - block_w/2,
+                    block_w, block_w,
+                    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= 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 void 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;
+     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;
+     }
+     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);
+             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);
+             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{
+         decode_q_branch(s, level+1, 2*x+0, 2*y+0);
+         decode_q_branch(s, level+1, 2*x+1, 2*y+0);
+         decode_q_branch(s, level+1, 2*x+0, 2*y+1);
+         decode_q_branch(s, level+1, 2*x+1, 2*y+1);
+     }
+ }
+ 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= 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<3; 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 -1;\
+     }\
+     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);
+         s->chroma_h_shift= get_symbol(&s->c, s->header_state, 0);
+         s->chroma_v_shift= get_symbol(&s->c, s->header_state, 0);
+         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<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 -1;
+                 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", s->spatial_decomposition_type);
+         return -1;
+     }
+     if(FFMIN(s->avctx-> width>>s->chroma_h_shift,
+              s->avctx->height>>s->chroma_v_shift) >> (s->spatial_decomposition_count-1) <= 0){
+         av_log(s->avctx, AV_LOG_ERROR, "spatial_decomposition_count %d too large for size", s->spatial_decomposition_count);
+         return -1;
+     }
+     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", s->block_max_depth);
+         s->block_max_depth= 0;
+         return -1;
+     }
+     return 0;
+ }
+ static av_cold int decode_init(AVCodecContext *avctx)
+ {
+     avctx->pix_fmt= PIX_FMT_YUV420P;
+     ff_snow_common_init(avctx);
+     return 0;
+ }
+ static void decode_blocks(SnowContext *s){
+     int x, y;
+     int w= s->b_width;
+     int h= s->b_height;
+     for(y=0; y<h; y++){
+         for(x=0; x<w; x++){
+             decode_q_branch(s, 0, x, y);
+         }
+     }
+ }
+ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, 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;
+     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(decode_header(s)<0)
+         return -1;
+     ff_snow_common_init_after_header(avctx);
+     // realloc slice buffer for the case that spatial_decomposition_count changed
+     ff_slice_buffer_destroy(&s->sb);
+     ff_slice_buffer_init(&s->sb, s->plane[0].height, (MB_SIZE >> s->block_max_depth) + s->spatial_decomposition_count * 8 + 1, s->plane[0].width, s->spatial_idwt_buffer);
+     for(plane_index=0; plane_index<3; 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(ff_snow_frame_start(s) < 0)
+         return -1;
+     //keyframe flag duplication mess FIXME
+     if(avctx->debug&FF_DEBUG_PICT_INFO)
+         av_log(avctx, AV_LOG_ERROR, "keyframe:%d qlog:%d\n", s->keyframe, s->qlog);
+     decode_blocks(s);
+     for(plane_index=0; plane_index<3; 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_w    = plane_index ? block_size/2 : 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_w*mb_y;
+             int slice_h = block_w*(mb_y+1);
+             if (!(s->keyframe || s->avctx->debug&512)){
+                 slice_starty = FFMAX(0, slice_starty - (block_w >> 1));
+                 slice_h -= (block_w >> 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_w * our_mb_start) >> (s->spatial_decomposition_count - level)) + s->spatial_decomposition_count - level + extra: 0);
+                     end_y = (((block_w * 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_w >> (1+s->spatial_decomposition_count - level)));
+                         end_y = FFMAX(0, end_y - (block_w >> (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, 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))
+         *picture= s->current_picture;
+     else
+         *picture= s->mconly_picture;
+     *data_size = sizeof(AVFrame);
+     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",
+     .type           = AVMEDIA_TYPE_VIDEO,
+     .id             = 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*/,
+     .long_name = NULL_IF_CONFIG_SMALL("Snow"),
+ };
diff --combined libavcodec/snowenc.c
index 0000000000000000000000000000000000000000,4926eef5d21216f23bdba042a35669056bacf8b4..6f00941389043dfa5b6244f752892680a48f50bc
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,1915 +1,2036 @@@
 - * This file is part of Libav.
+ /*
+  * Copyright (C) 2004 Michael Niedermayer <michaelni@gmx.at>
+  *
 - * Libav is free software; you can redistribute it and/or
++ * This file is part of FFmpeg.
+  *
 - * Libav is distributed in the hope that it will be useful,
++ * FFmpeg is free software; you can redistribute it and/or
+  * modify it under the terms of the GNU Lesser General Public
+  * License as published by the Free Software Foundation; either
+  * version 2.1 of the License, or (at your option) any later version.
+  *
 - * License along with Libav; if not, write to the Free Software
++ * FFmpeg is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  * Lesser General Public License for more details.
+  *
+  * You should have received a copy of the GNU Lesser General Public
++ * 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 "dsputil.h"
+ #include "dwt.h"
+ #include "snow.h"
+ #include "rangecoder.h"
+ #include "mathops.h"
+ #include "mpegvideo.h"
+ #include "h263.h"
+ #undef NDEBUG
+ #include <assert.h>
+ #define QUANTIZE2 0
+ #if QUANTIZE2==1
+ #define Q2_STEP 8
+ static void find_sse(SnowContext *s, Plane *p, int *score, int score_stride, IDWTELEM *r0, IDWTELEM *r1, int level, int orientation){
+     SubBand *b= &p->band[level][orientation];
+     int x, y;
+     int xo=0;
+     int yo=0;
+     int step= 1 << (s->spatial_decomposition_count - level);
+     if(orientation&1)
+         xo= step>>1;
+     if(orientation&2)
+         yo= step>>1;
+     //FIXME bias for nonzero ?
+     //FIXME optimize
+     memset(score, 0, sizeof(*score)*score_stride*((p->height + Q2_STEP-1)/Q2_STEP));
+     for(y=0; y<p->height; y++){
+         for(x=0; x<p->width; x++){
+             int sx= (x-xo + step/2) / step / Q2_STEP;
+             int sy= (y-yo + step/2) / step / Q2_STEP;
+             int v= r0[x + y*p->width] - r1[x + y*p->width];
+             assert(sx>=0 && sy>=0 && sx < score_stride);
+             v= ((v+8)>>4)<<4;
+             score[sx + sy*score_stride] += v*v;
+             assert(score[sx + sy*score_stride] >= 0);
+         }
+     }
+ }
+ static void dequantize_all(SnowContext *s, Plane *p, IDWTELEM *buffer, int width, int height){
+     int level, orientation;
+     for(level=0; level<s->spatial_decomposition_count; level++){
+         for(orientation=level ? 1 : 0; orientation<4; orientation++){
+             SubBand *b= &p->band[level][orientation];
+             IDWTELEM *dst= buffer + (b->ibuf - s->spatial_idwt_buffer);
+             dequantize(s, b, dst, b->stride);
+         }
+     }
+ }
+ static void dwt_quantize(SnowContext *s, Plane *p, DWTELEM *buffer, int width, int height, int stride, int type){
+     int level, orientation, ys, xs, x, y, pass;
+     IDWTELEM best_dequant[height * stride];
+     IDWTELEM idwt2_buffer[height * stride];
+     const int score_stride= (width + 10)/Q2_STEP;
+     int best_score[(width + 10)/Q2_STEP * (height + 10)/Q2_STEP]; //FIXME size
+     int score[(width + 10)/Q2_STEP * (height + 10)/Q2_STEP]; //FIXME size
+     int threshold= (s->m.lambda * s->m.lambda) >> 6;
+     //FIXME pass the copy cleanly ?
+ //    memcpy(dwt_buffer, buffer, height * stride * sizeof(DWTELEM));
+     ff_spatial_dwt(buffer, width, height, stride, type, s->spatial_decomposition_count);
+     for(level=0; level<s->spatial_decomposition_count; level++){
+         for(orientation=level ? 1 : 0; orientation<4; orientation++){
+             SubBand *b= &p->band[level][orientation];
+             IDWTELEM *dst= best_dequant + (b->ibuf - s->spatial_idwt_buffer);
+              DWTELEM *src=       buffer + (b-> buf - s->spatial_dwt_buffer);
+             assert(src == b->buf); // code does not depend on this but it is true currently
+             quantize(s, b, dst, src, b->stride, s->qbias);
+         }
+     }
+     for(pass=0; pass<1; pass++){
+         if(s->qbias == 0) //keyframe
+             continue;
+         for(level=0; level<s->spatial_decomposition_count; level++){
+             for(orientation=level ? 1 : 0; orientation<4; orientation++){
+                 SubBand *b= &p->band[level][orientation];
+                 IDWTELEM *dst= idwt2_buffer + (b->ibuf - s->spatial_idwt_buffer);
+                 IDWTELEM *best_dst= best_dequant + (b->ibuf - s->spatial_idwt_buffer);
+                 for(ys= 0; ys<Q2_STEP; ys++){
+                     for(xs= 0; xs<Q2_STEP; xs++){
+                         memcpy(idwt2_buffer, best_dequant, height * stride * sizeof(IDWTELEM));
+                         dequantize_all(s, p, idwt2_buffer, width, height);
+                         ff_spatial_idwt(idwt2_buffer, width, height, stride, type, s->spatial_decomposition_count);
+                         find_sse(s, p, best_score, score_stride, idwt2_buffer, s->spatial_idwt_buffer, level, orientation);
+                         memcpy(idwt2_buffer, best_dequant, height * stride * sizeof(IDWTELEM));
+                         for(y=ys; y<b->height; y+= Q2_STEP){
+                             for(x=xs; x<b->width; x+= Q2_STEP){
+                                 if(dst[x + y*b->stride]<0) dst[x + y*b->stride]++;
+                                 if(dst[x + y*b->stride]>0) dst[x + y*b->stride]--;
+                                 //FIXME try more than just --
+                             }
+                         }
+                         dequantize_all(s, p, idwt2_buffer, width, height);
+                         ff_spatial_idwt(idwt2_buffer, width, height, stride, type, s->spatial_decomposition_count);
+                         find_sse(s, p, score, score_stride, idwt2_buffer, s->spatial_idwt_buffer, level, orientation);
+                         for(y=ys; y<b->height; y+= Q2_STEP){
+                             for(x=xs; x<b->width; x+= Q2_STEP){
+                                 int score_idx= x/Q2_STEP + (y/Q2_STEP)*score_stride;
+                                 if(score[score_idx] <= best_score[score_idx] + threshold){
+                                     best_score[score_idx]= score[score_idx];
+                                     if(best_dst[x + y*b->stride]<0) best_dst[x + y*b->stride]++;
+                                     if(best_dst[x + y*b->stride]>0) best_dst[x + y*b->stride]--;
+                                     //FIXME copy instead
+                                 }
+                             }
+                         }
+                     }
+                 }
+             }
+         }
+     }
+     memcpy(s->spatial_idwt_buffer, best_dequant, height * stride * sizeof(IDWTELEM)); //FIXME work with that directly instead of copy at the end
+ }
+ #endif /* QUANTIZE2==1 */
+ #if CONFIG_SNOW_ENCODER
+ static av_cold int encode_init(AVCodecContext *avctx)
+ {
+     SnowContext *s = avctx->priv_data;
+     int plane_index;
+     if(avctx->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL){
+         av_log(avctx, AV_LOG_ERROR, "This codec is under development, files encoded with it may not be decodable with future versions!!!\n"
+                "Use vstrict=-2 / -strict -2 to use it anyway.\n");
+         return -1;
+     }
+     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;
+     }
+     ff_snow_common_init(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((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));
+     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->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));
+     avctx->coded_frame= &s->current_picture;
+     switch(avctx->pix_fmt){
+ //    case PIX_FMT_YUV444P:
+ //    case PIX_FMT_YUV422P:
+     case PIX_FMT_YUV420P:
+     case PIX_FMT_GRAY8:
+ //    case PIX_FMT_YUV411P:
+ //    case PIX_FMT_YUV410P:
+         s->colorspace_type= 0;
+         break;
+ /*    case 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);
+     s->chroma_h_shift= 1;
+     s->chroma_v_shift= 1;
+     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);
+     s->avctx->get_buffer(s->avctx, &s->input_picture);
+     if(s->avctx->me_method == ME_ITER){
+         int i;
+         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(size*sizeof(int16_t[2]));
+             s->ref_scores[i]= av_mallocz(size*sizeof(uint32_t));
+         }
+     }
+     return 0;
+ }
+ //near copy & paste from dsputil, FIXME
+ static int pix_sum(uint8_t * pix, int line_size, int w)
+ {
+     int s, i, j;
+     s = 0;
+     for (i = 0; i < w; 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_squareTbl + 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;
+ }
+ //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 + y*uvstride)*block_w/2,
+                                 s->input_picture.data[2] + (x + y*uvstride)*block_w/2};
+     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;
+     assert(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;
+     assert(c->  stride ==   stride);
+     assert(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);
+         assert(ref_mx >= c->xmin);
+         assert(ref_mx <= c->xmax);
+         assert(ref_my >= c->ymin);
+         assert(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);
+     l= (sum + block_s/2)/block_s;
+     iscore = pix_norm1(current_data[0], stride, block_w) - 2*l*sum + l*l*block_s;
+     block_s= block_w*block_w>>2;
+     sum = pix_sum(current_data[1], uvstride, block_w>>1);
+     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>>1);
+     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;
+     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);
+     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);
+     assert(iscore < 255*255*256 + s->lambda2*10);
+     assert(iscore >= 0);
+     assert(l>=0 && l<=255);
+     assert(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);
+         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/2 : block_size;
+     const uint8_t *obmc  = plane_index ? obmc_tab[s->block_max_depth+1] : obmc_tab[s->block_max_depth];
+     const int obmc_stride= plane_index ? block_size : 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;
+     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_w*mb_y2 + block_w/2;
+         add_yblock(s, 0, NULL, dst + ((i&1)+(i>>1)*obmc_stride)*block_w, NULL, obmc,
+                     x, y, block_w, block_w, 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_w); 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_w*mb_y - block_w/2))*obmc_stride;
+                 int obmc_v= obmc[index];
+                 int d;
+                 if(y<0) obmc_v += obmc[index + block_w*obmc_stride];
+                 if(x<0) obmc_v += obmc[index + block_w];
+                 if(y+block_w>h) obmc_v += obmc[index - block_w*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(((ab<<LOG2_OBMC_MAX) + aa/2)/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, const uint8_t *obmc_edged){
+     Plane *p= &s->plane[plane_index];
+     const int block_size = MB_SIZE >> s->block_max_depth;
+     const int block_w    = plane_index ? block_size/2 : block_size;
+     const int obmc_stride= plane_index ? block_size : 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[ref_stride*(2*MB_SIZE+HTAPS_MAX-1)];
+     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_w*mb_y - block_w/2;
+     int x0= FFMAX(0,-sx);
+     int y0= FFMAX(0,-sy);
+     int x1= FFMIN(block_w*2, w-sx);
+     int y1= FFMIN(block_w*2, h-sy);
+     int i,x,y;
+     ff_snow_pred_block(s, cur, tmp, ref_stride, sx, sy, block_w*2, block_w*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*obmc_stride;
+         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_w;
+         else
+             y0 = block_w;
+         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 + off, dst + off, ref_stride, 16);
+             }
+         }
+     }else{
+         assert(block_w==8);
+         distortion = s->dsp.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/2 : block_size;
+     const uint8_t *obmc  = plane_index ? obmc_tab[s->block_max_depth+1] : obmc_tab[s->block_max_depth];
+     const int obmc_stride= plane_index ? block_size : 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);
+     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_w*mb_y2 + block_w/2;
+         add_yblock(s, 0, NULL, zero_dst, dst, obmc,
+                    x, y, block_w, block_w, 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_w; y2++)
+             memcpy(dst + x + y2*ref_stride, src + x + y2*ref_stride, block_w);
+         if(x<0){
+             for(y2= y; y2<y+block_w; y2++)
+                 memcpy(dst + x + y2*ref_stride, src + x + y2*ref_stride, -x);
+         }
+         if(x+block_w > w){
+             for(y2= y; y2<y+block_w; y2++)
+                 memcpy(dst + w + y2*ref_stride, src + w + y2*ref_stride, x+block_w - w);
+         }
+         assert(block_w== 8 || block_w==16);
+         distortion += s->dsp.me_cmp[block_w==8](&s->m, src + x + y*ref_stride, dst + x + y*ref_stride, ref_stride, block_w);
+     }
+     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, IDWTELEM *src, 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[w*h];
+         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);
+                         assert(v);
+                     }else{
+                         run--;
+                         assert(!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 + quant3bA[l2&0xFF] + 3*quant3bA[t2&0xFF]], v<0);
+                 }
+             }
+         }
+     }
+     return 0;
+ }
+ static int encode_subband(SnowContext *s, SubBand *b, IDWTELEM *src, 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, const uint8_t *obmc_edged, 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;
+     int rd, index, value;
+     assert(mb_x>=0 && mb_y>=0);
+     assert(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, const uint8_t *obmc_edged, 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]= {block[0], block[1], block[b_stride], block[b_stride+1]};
+     int rd, index, value;
+     assert(mb_x>=0 && mb_y>=0);
+     assert(mb_x<b_stride);
+     assert(((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[b_w*2][b_w*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;
+                     memcpy(obmc_edged, obmc_tab[s->block_max_depth], b_w*b_w*4);
+                     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 sx= block_w*mb_x - block_w/2;
+                     const int sy= block_w*mb_y - block_w/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_w*2; y++)
+                         memcpy(dst + sx + y*stride, src + sx + y*stride, block_w*2);
+                     if(sx<0){
+                         for(y=sy; y<sy+block_w*2; y++)
+                             memcpy(dst + sx + y*stride, src + sx + y*stride, -sx);
+                     }
+                     if(sx+block_w*2 > w){
+                         for(y=sy; y<sy+block_w*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<3; 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= 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= 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<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);
+         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<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<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*log(qscale / (float)FF_QP2LAMBDA)/log(2))
+            + 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= 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 */
+     coef_sum = (uint64_t)coef_sum * coef_sum >> 16;
+     assert(coef_sum < INT_MAX);
+     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, width, height, width, s->spatial_decomposition_type, s->spatial_decomposition_count);
+             for(y=0; y<height; y++){
+                 for(x=0; x<width; x++){
+                     int64_t d= s->spatial_idwt_buffer[x + y*width]*16;
+                     error += d*d;
+                 }
+             }
+             b->qlog= (int)(log(352256.0/sqrt(error)) / log(pow(2.0, 1.0/QROOT))+0.5);
+         }
+     }
+ }
+ static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, void *data){
+     SnowContext *s = avctx->priv_data;
+     RangeCoder * const c= &s->c;
+     AVFrame *pict = data;
+     const int width= s->avctx->width;
+     const int height= s->avctx->height;
+     int level, orientation, plane_index, i, y;
+     uint8_t rc_header_bak[sizeof(s->header_state)];
+     uint8_t rc_block_bak[sizeof(s->block_state)];
+     ff_init_range_encoder(c, buf, buf_size);
+     ff_build_rac_states(c, 0.05*(1LL<<32), 256-8);
+     for(i=0; i<3; i++){
+         int shift= !!i;
+         for(y=0; y<(height>>shift); y++)
+             memcpy(&s->input_picture.data[i][y * s->input_picture.linesize[i]],
+                    &pict->data[i][y * pict->linesize[i]],
+                    width>>shift);
+     }
+     s->new_picture = *pict;
+     s->m.picture_number= avctx->frame_number;
+     if(avctx->flags&CODEC_FLAG_PASS2){
+         s->m.pict_type =
+         pict->pict_type= s->m.rc_context.entry[avctx->frame_number].new_pict_type;
+         s->keyframe= pict->pict_type==AV_PICTURE_TYPE_I;
+         if(!(avctx->flags&CODEC_FLAG_QSCALE)) {
+             pict->quality= ff_rate_estimate_qscale(&s->m, 0);
+             if (pict->quality < 0)
+                 return -1;
+         }
+     }else{
+         s->keyframe= avctx->gop_size==0 || avctx->frame_number % avctx->gop_size == 0;
+         s->m.pict_type=
+         pict->pict_type= s->keyframe ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P;
+     }
+     if(s->pass1_rc && avctx->frame_number == 0)
+         pict->quality= 2*FF_QP2LAMBDA;
+     if(pict->quality){
+         s->qlog= qscale2qlog(pict->quality);
+         s->lambda = pict->quality * 3/2;
+     }
+     if(s->qlog < 0 || (!pict->quality && (avctx->flags & CODEC_FLAG_QSCALE))){
+         s->qlog= LOSSLESS_QLOG;
+         s->lambda = 0;
+     }//else keep previous frame's qlog until after motion estimation
+     ff_snow_frame_start(s);
+     s->m.current_picture_ptr= &s->m.current_picture;
+     s->m.last_picture.f.pts = s->m.current_picture.f.pts;
+     s->m.current_picture.f.pts = pict->pts;
+     if(pict->pict_type == AV_PICTURE_TYPE_P){
+         int block_width = (width +15)>>4;
+         int block_height= (height+15)>>4;
+         int stride= s->current_picture.linesize[0];
+         assert(s->current_picture.data[0]);
+         assert(s->last_picture[0].data[0]);
+         s->m.avctx= s->avctx;
+         s->m.current_picture.f.data[0] = s->current_picture.data[0];
+         s->m.   last_picture.f.data[0] = s->last_picture[0].data[0];
+         s->m.    new_picture.f.data[0] = s->  input_picture.data[0];
+         s->m.   last_picture_ptr= &s->m.   last_picture;
+         s->m.linesize=
+         s->m.   last_picture.f.linesize[0] =
+         s->m.    new_picture.f.linesize[0] =
+         s->m.current_picture.f.linesize[0] = stride;
+         s->m.uvlinesize= s->current_picture.linesize[1];
+         s->m.width = width;
+         s->m.height= height;
+         s->m.mb_width = block_width;
+         s->m.mb_height= block_height;
+         s->m.mb_stride=   s->m.mb_width+1;
+         s->m.b8_stride= 2*s->m.mb_width+1;
+         s->m.f_code=1;
+         s->m.pict_type= pict->pict_type;
+         s->m.me_method= s->avctx->me_method;
+         s->m.me.scene_change_score=0;
+         s->m.flags= s->avctx->flags;
+         s->m.quarter_sample= (s->avctx->flags & CODEC_FLAG_QPEL)!=0;
+         s->m.out_format= FMT_H263;
+         s->m.unrestricted_mv= 1;
+         s->m.lambda = s->lambda;
+         s->m.qscale= (s->m.lambda*139 + FF_LAMBDA_SCALE*64) >> (FF_LAMBDA_SHIFT + 7);
+         s->lambda2= s->m.lambda2= (s->m.lambda*s->m.lambda + FF_LAMBDA_SCALE/2) >> FF_LAMBDA_SHIFT;
+         s->m.dsp= s->dsp; //move
+         ff_init_me(&s->m);
+         s->dsp= s->m.dsp;
+     }
+     if(s->pass1_rc){
+         memcpy(rc_header_bak, s->header_state, sizeof(s->header_state));
+         memcpy(rc_block_bak, s->block_state, sizeof(s->block_state));
+     }
+ redo_frame:
+     if(pict->pict_type == AV_PICTURE_TYPE_I)
+         s->spatial_decomposition_count= 5;
+     else
+         s->spatial_decomposition_count= 5;
+     s->m.pict_type = pict->pict_type;
+     s->qbias= pict->pict_type == AV_PICTURE_TYPE_P ? 2 : 0;
+     ff_snow_common_init_after_header(avctx);
+     if(s->last_spatial_decomposition_count != s->spatial_decomposition_count){
+         for(plane_index=0; plane_index<3; plane_index++){
+             calculate_visual_weight(s, &s->plane[plane_index]);
+         }
+     }
+     encode_header(s);
+     s->m.misc_bits = 8*(s->c.bytestream - s->c.bytestream_start);
+     encode_blocks(s, 1);
+     s->m.mv_bits = 8*(s->c.bytestream - s->c.bytestream_start) - s->m.misc_bits;
+     for(plane_index=0; plane_index<3; plane_index++){
+         Plane *p= &s->plane[plane_index];
+         int w= p->width;
+         int h= p->height;
+         int x, y;
+ //        int bits= put_bits_count(&s->c.pb);
+         if (!s->memc_only) {
+             //FIXME optimize
+             if(pict->data[plane_index]) //FIXME gray hack
+                 for(y=0; y<h; y++){
+                     for(x=0; x<w; x++){
+                         s->spatial_idwt_buffer[y*w + x]= pict->data[plane_index][y*pict->linesize[plane_index] + x]<<FRAC_BITS;
+                     }
+                 }
+             predict_plane(s, s->spatial_idwt_buffer, plane_index, 0);
+             if(   plane_index==0
+                && pict->pict_type == AV_PICTURE_TYPE_P
+                && !(avctx->flags&CODEC_FLAG_PASS2)
+                && s->m.me.scene_change_score > s->avctx->scenechange_threshold){
+                 ff_init_range_encoder(c, buf, buf_size);
+                 ff_build_rac_states(c, 0.05*(1LL<<32), 256-8);
+                 pict->pict_type= AV_PICTURE_TYPE_I;
+                 s->keyframe=1;
+                 s->current_picture.key_frame=1;
+                 goto redo_frame;
+             }
+             if(s->qlog == LOSSLESS_QLOG){
+                 for(y=0; y<h; y++){
+                     for(x=0; x<w; x++){
+                         s->spatial_dwt_buffer[y*w + x]= (s->spatial_idwt_buffer[y*w + x] + (1<<(FRAC_BITS-1))-1)>>FRAC_BITS;
+                     }
+                 }
+             }else{
+                 for(y=0; y<h; y++){
+                     for(x=0; x<w; x++){
+                         s->spatial_dwt_buffer[y*w + x]=s->spatial_idwt_buffer[y*w + x]<<ENCODER_EXTRA_BITS;
+                     }
+                 }
+             }
+             /*  if(QUANTIZE2)
+                 dwt_quantize(s, p, s->spatial_dwt_buffer, w, h, w, s->spatial_decomposition_type);
+             else*/
+                 ff_spatial_dwt(s->spatial_dwt_buffer, w, h, w, s->spatial_decomposition_type, s->spatial_decomposition_count);
+             if(s->pass1_rc && plane_index==0){
+                 int delta_qlog = ratecontrol_1pass(s, pict);
+                 if (delta_qlog <= INT_MIN)
+                     return -1;
+                 if(delta_qlog){
+                     //reordering qlog in the bitstream would eliminate this reset
+                     ff_init_range_encoder(c, buf, buf_size);
+                     memcpy(s->header_state, rc_header_bak, sizeof(s->header_state));
+                     memcpy(s->block_state, rc_block_bak, sizeof(s->block_state));
+                     encode_header(s);
+                     encode_blocks(s, 0);
+                 }
+             }
+             for(level=0; level<s->spatial_decomposition_count; level++){
+                 for(orientation=level ? 1 : 0; orientation<4; orientation++){
+                     SubBand *b= &p->band[level][orientation];
+                     if(!QUANTIZE2)
+                         quantize(s, b, b->ibuf, b->buf, b->stride, s->qbias);
+                     if(orientation==0)
+                         decorrelate(s, b, b->ibuf, b->stride, pict->pict_type == AV_PICTURE_TYPE_P, 0);
+                     encode_subband(s, b, b->ibuf, b->parent ? b->parent->ibuf : NULL, b->stride, orientation);
+                     assert(b->parent==NULL || b->parent->stride == b->stride*2);
+                     if(orientation==0)
+                         correlate(s, b, b->ibuf, b->stride, 1, 0);
+                 }
+             }
+             for(level=0; level<s->spatial_decomposition_count; level++){
+                 for(orientation=level ? 1 : 0; orientation<4; orientation++){
+                     SubBand *b= &p->band[level][orientation];
+                     dequantize(s, b, b->ibuf, b->stride);
+                 }
+             }
+             ff_spatial_idwt(s->spatial_idwt_buffer, w, h, w, s->spatial_decomposition_type, s->spatial_decomposition_count);
+             if(s->qlog == LOSSLESS_QLOG){
+                 for(y=0; y<h; y++){
+                     for(x=0; x<w; x++){
+                         s->spatial_idwt_buffer[y*w + x]<<=FRAC_BITS;
+                     }
+                 }
+             }
+             predict_plane(s, s->spatial_idwt_buffer, plane_index, 1);
+         }else{
+             //ME/MC only
+             if(pict->pict_type == AV_PICTURE_TYPE_I){
+                 for(y=0; y<h; y++){
+                     for(x=0; x<w; x++){
+                         s->current_picture.data[plane_index][y*s->current_picture.linesize[plane_index] + x]=
+                             pict->data[plane_index][y*pict->linesize[plane_index] + x];
+                     }
+                 }
+             }else{
+                 memset(s->spatial_idwt_buffer, 0, sizeof(IDWTELEM)*w*h);
+                 predict_plane(s, s->spatial_idwt_buffer, plane_index, 1);
+             }
+         }
+         if(s->avctx->flags&CODEC_FLAG_PSNR){
+             int64_t error= 0;
+             if(pict->data[plane_index]) //FIXME gray hack
+                 for(y=0; y<h; y++){
+                     for(x=0; x<w; x++){
+                         int d= s->current_picture.data[plane_index][y*s->current_picture.linesize[plane_index] + x] - pict->data[plane_index][y*pict->linesize[plane_index] + x];
+                         error += d*d;
+                     }
+                 }
+             s->avctx->error[plane_index] += error;
+             s->current_picture.error[plane_index] = error;
+         }
+     }
+     update_last_header_values(s);
+     ff_snow_release_buffer(avctx);
+     s->current_picture.coded_picture_number = avctx->frame_number;
+     s->current_picture.pict_type = pict->pict_type;
+     s->current_picture.quality = pict->quality;
+     s->m.frame_bits = 8*(s->c.bytestream - s->c.bytestream_start);
+     s->m.p_tex_bits = s->m.frame_bits - s->m.misc_bits - s->m.mv_bits;
+     s->m.current_picture.f.display_picture_number =
+     s->m.current_picture.f.coded_picture_number   = avctx->frame_number;
+     s->m.current_picture.f.quality                = pict->quality;
+     s->m.total_bits += 8*(s->c.bytestream - s->c.bytestream_start);
+     if(s->pass1_rc)
+         if (ff_rate_estimate_qscale(&s->m, 0) < 0)
+             return -1;
+     if(avctx->flags&CODEC_FLAG_PASS1)
+         ff_write_pass1_stats(&s->m);
+     s->m.last_pict_type = s->m.pict_type;
+     avctx->frame_bits = s->m.frame_bits;
+     avctx->mv_bits = s->m.mv_bits;
+     avctx->misc_bits = s->m.misc_bits;
+     avctx->p_tex_bits = s->m.p_tex_bits;
+     emms_c();
+     return ff_rac_terminate(c);
+ }
+ static av_cold int encode_end(AVCodecContext *avctx)
+ {
+     SnowContext *s = avctx->priv_data;
+     ff_snow_common_end(s);
+     if (s->input_picture.data[0])
+         avctx->release_buffer(avctx, &s->input_picture);
+     av_free(avctx->stats_out);
+     return 0;
+ }
+ #define OFFSET(x) offsetof(SnowContext, x)
+ #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
+ static const AVOption options[] = {
+     { "memc_only",      "Only do ME/MC (I frames -> ref, P frame -> ME+MC).",   OFFSET(memc_only), AV_OPT_TYPE_INT, { 0 }, 0, 1, VE },
+     { NULL },
+ };
+ static const AVClass snowenc_class = {
+     .class_name = "snow encoder",
+     .item_name  = av_default_item_name,
+     .option     = options,
+     .version    = LIBAVUTIL_VERSION_INT,
+ };
+ AVCodec ff_snow_encoder = {
+     .name           = "snow",
+     .type           = AVMEDIA_TYPE_VIDEO,
+     .id             = CODEC_ID_SNOW,
+     .priv_data_size = sizeof(SnowContext),
+     .init           = encode_init,
+     .encode         = encode_frame,
+     .close          = encode_end,
+     .long_name = NULL_IF_CONFIG_SMALL("Snow"),
+     .priv_class     = &snowenc_class,
+ };
+ #endif
++
++
++#ifdef TEST
++#undef malloc
++#undef free
++#undef printf
++
++#include "libavutil/lfg.h"
++#include "libavutil/mathematics.h"
++
++int main(void){
++    int width=256;
++    int height=256;
++    int buffer[2][width*height];
++    SnowContext s;
++    int i;
++    AVLFG prng;
++    s.spatial_decomposition_count=6;
++    s.spatial_decomposition_type=1;
++
++    av_lfg_init(&prng, 1);
++
++    printf("testing 5/3 DWT\n");
++    for(i=0; i<width*height; i++)
++        buffer[0][i] = buffer[1][i] = av_lfg_get(&prng) % 54321 - 12345;
++
++    ff_spatial_dwt(buffer[0], width, height, width, s.spatial_decomposition_type, s.spatial_decomposition_count);
++    ff_spatial_idwt(buffer[0], width, height, width, s.spatial_decomposition_type, s.spatial_decomposition_count);
++
++    for(i=0; i<width*height; i++)
++        if(buffer[0][i]!= buffer[1][i]) printf("fsck: %6d %12d %7d\n",i, buffer[0][i], buffer[1][i]);
++
++    printf("testing 9/7 DWT\n");
++    s.spatial_decomposition_type=0;
++    for(i=0; i<width*height; i++)
++        buffer[0][i] = buffer[1][i] = av_lfg_get(&prng) % 54321 - 12345;
++
++    ff_spatial_dwt(buffer[0], width, height, width, s.spatial_decomposition_type, s.spatial_decomposition_count);
++    ff_spatial_idwt(buffer[0], width, height, width, s.spatial_decomposition_type, s.spatial_decomposition_count);
++
++    for(i=0; i<width*height; i++)
++        if(FFABS(buffer[0][i] - buffer[1][i])>20) printf("fsck: %6d %12d %7d\n",i, buffer[0][i], buffer[1][i]);
++
++    {
++    int level, orientation, x, y;
++    int64_t errors[8][4];
++    int64_t g=0;
++
++        memset(errors, 0, sizeof(errors));
++        s.spatial_decomposition_count=3;
++        s.spatial_decomposition_type=0;
++        for(level=0; level<s.spatial_decomposition_count; level++){
++            for(orientation=level ? 1 : 0; orientation<4; orientation++){
++                int w= width  >> (s.spatial_decomposition_count-level);
++                int h= height >> (s.spatial_decomposition_count-level);
++                int stride= width  << (s.spatial_decomposition_count-level);
++                DWTELEM *buf= buffer[0];
++                int64_t error=0;
++
++                if(orientation&1) buf+=w;
++                if(orientation>1) buf+=stride>>1;
++
++                memset(buffer[0], 0, sizeof(int)*width*height);
++                buf[w/2 + h/2*stride]= 256*256;
++                ff_spatial_idwt(buffer[0], width, height, width, s.spatial_decomposition_type, s.spatial_decomposition_count);
++                for(y=0; y<height; y++){
++                    for(x=0; x<width; x++){
++                        int64_t d= buffer[0][x + y*width];
++                        error += d*d;
++                        if(FFABS(width/2-x)<9 && FFABS(height/2-y)<9 && level==2) printf("%8"PRId64" ", d);
++                    }
++                    if(FFABS(height/2-y)<9 && level==2) printf("\n");
++                }
++                error= (int)(sqrt(error)+0.5);
++                errors[level][orientation]= error;
++                if(g) g=av_gcd(g, error);
++                else g= error;
++            }
++        }
++        printf("static int const visual_weight[][4]={\n");
++        for(level=0; level<s.spatial_decomposition_count; level++){
++            printf("  {");
++            for(orientation=0; orientation<4; orientation++){
++                printf("%8"PRId64",", errors[level][orientation]/g);
++            }
++            printf("},\n");
++        }
++        printf("};\n");
++        {
++            int level=2;
++            int w= width  >> (s.spatial_decomposition_count-level);
++            //int h= height >> (s.spatial_decomposition_count-level);
++            int stride= width  << (s.spatial_decomposition_count-level);
++            DWTELEM *buf= buffer[0];
++            int64_t error=0;
++
++            buf+=w;
++            buf+=stride>>1;
++
++            memset(buffer[0], 0, sizeof(int)*width*height);
++            for(y=0; y<height; y++){
++                for(x=0; x<width; x++){
++                    int tab[4]={0,2,3,1};
++                    buffer[0][x+width*y]= 256*256*tab[(x&1) + 2*(y&1)];
++                }
++            }
++            ff_spatial_dwt(buffer[0], width, height, width, s.spatial_decomposition_type, s.spatial_decomposition_count);
++            for(y=0; y<height; y++){
++                for(x=0; x<width; x++){
++                    int64_t d= buffer[0][x + y*width];
++                    error += d*d;
++                    if(FFABS(width/2-x)<9 && FFABS(height/2-y)<9) printf("%8"PRId64" ", d);
++                }
++                if(FFABS(height/2-y)<9) printf("\n");
++            }
++        }
++
++    }
++    return 0;
++}
++#endif /* TEST */
diff --combined libavcodec/tiffenc.c
index 9656cd9b6837d54fb28a4093512823953b2e7520,3b2b82991b945b2bbd8443350832b7c4addb2c19..94ed9eb5fbb376a492020f145bda095084d4cac2
@@@ -2,20 -2,20 +2,20 @@@
   * TIFF image encoder
   * Copyright (c) 2007 Bartlomiej Wolowiec
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * FFmpeg is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 2.1 of the License, or (at your option) any later version.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * FFmpeg is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
 - * License along with Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
@@@ -32,7 -32,6 +32,7 @@@
  #if CONFIG_ZLIB
  #include <zlib.h>
  #endif
 +#include "libavutil/opt.h"
  #include "bytestream.h"
  #include "tiff.h"
  #include "rle.h"
@@@ -66,7 -65,6 +66,7 @@@ typedef struct TiffEncoderContext 
      int buf_size;                       ///< buffer size
      uint16_t subsampling[2];            ///< YUV subsampling factors
      struct LZWEncodeState *lzws;        ///< LZW Encode state
 +    uint32_t dpi;                       ///< image resolution in DPI
  } TiffEncoderContext;
  
  
@@@ -216,8 -214,8 +216,8 @@@ static int encode_frame(AVCodecContext 
      uint32_t *strip_sizes = NULL;
      uint32_t *strip_offsets = NULL;
      int bytes_per_row;
 -    uint32_t res[2] = { 72, 1 };        // image resolution (72/1)
 -    static const uint16_t bpp_tab[] = { 8, 8, 8, 8 };
 +    uint32_t res[2] = { s->dpi, 1 };        // image resolution (72/1)
 +    uint16_t bpp_tab[] = { 8, 8, 8, 8 };
      int ret = -1;
      int is_yuv = 0;
      uint8_t *yuv_line = NULL;
      p->key_frame = 1;
      avctx->coded_frame= &s->picture;
  
+ #if FF_API_TIFFENC_COMPLEVEL
+     if (avctx->compression_level != FF_COMPRESSION_DEFAULT)
+         av_log(avctx, AV_LOG_WARNING, "Using compression_level to set compression "
+                "algorithm is deprecated. Please use the compression_algo private "
+                "option instead.\n");
      if (avctx->compression_level == 0) {
          s->compr = TIFF_RAW;
      } else if(avctx->compression_level == 2) {
          s->compr = TIFF_DEFLATE;
  #endif
      }
+ #endif
  
      s->width = avctx->width;
      s->height = avctx->height;
      s->subsampling[1] = 1;
  
      switch (avctx->pix_fmt) {
 +    case PIX_FMT_RGB48LE:
 +        s->bpp = 48;
 +        s->photometric_interpretation = 2;
 +        bpp_tab[0] = 16;
 +        bpp_tab[1] = 16;
 +        bpp_tab[2] = 16;
 +        bpp_tab[3] = 16;
 +        break;
      case PIX_FMT_RGB24:
          s->bpp = 24;
          s->photometric_interpretation = 2;
          s->photometric_interpretation = 3;
          break;
      case PIX_FMT_MONOBLACK:
 -        s->bpp = 1;
 -        s->photometric_interpretation = 1;
 -        break;
      case PIX_FMT_MONOWHITE:
          s->bpp = 1;
 -        s->photometric_interpretation = 0;
 +        s->photometric_interpretation = avctx->pix_fmt == PIX_FMT_MONOBLACK;
 +        bpp_tab[0] = 1;
          break;
      case PIX_FMT_YUV420P:
      case PIX_FMT_YUV422P:
          return -1;
      }
      if (!is_yuv)
 -        s->bpp_tab_size = (s->bpp >> 3);
 +        s->bpp_tab_size = (s->bpp >= 48) ? ((s->bpp + 7) >> 4):((s->bpp + 7) >> 3);
  
      if (s->compr == TIFF_DEFLATE || s->compr == TIFF_ADOBE_DEFLATE || s->compr == TIFF_LZW)
          //best choose for DEFLATE
@@@ -458,7 -456,6 +464,7 @@@ fail
  #define OFFSET(x) offsetof(TiffEncoderContext, x)
  #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
  static const AVOption options[] = {
 +    {"dpi", "set the image resolution (in dpi)", OFFSET(dpi), AV_OPT_TYPE_INT, {.dbl = 72}, 1, 0x10000, AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_ENCODING_PARAM},
      { "compression_algo", NULL, OFFSET(compr), AV_OPT_TYPE_INT, {TIFF_PACKBITS}, TIFF_RAW, TIFF_DEFLATE, VE, "compression_algo" },
      { "packbits", NULL, 0, AV_OPT_TYPE_CONST, {TIFF_PACKBITS}, 0, 0, VE, "compression_algo" },
      { "raw",      NULL, 0, AV_OPT_TYPE_CONST, {TIFF_RAW},      0, 0, VE, "compression_algo" },
@@@ -487,7 -484,7 +493,7 @@@ AVCodec ff_tiff_encoder = 
                                PIX_FMT_MONOBLACK, PIX_FMT_MONOWHITE,
                                PIX_FMT_YUV420P, PIX_FMT_YUV422P,
                                PIX_FMT_YUV444P, PIX_FMT_YUV410P,
 -                              PIX_FMT_YUV411P,
 +                              PIX_FMT_YUV411P, PIX_FMT_RGB48LE,
                                PIX_FMT_NONE},
      .long_name = NULL_IF_CONFIG_SMALL("TIFF image"),
      .priv_class     = &tiffenc_class,
diff --combined libavcodec/utils.c
index d58fce811c60029934c38a919afd281423be09a8,53440e0f848ed9c1b22fc9e686385550ae50ea5a..04a8a1e969d39019a278b866df671c0f41934aca
@@@ -3,20 -3,20 +3,20 @@@
   * Copyright (c) 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.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * FFmpeg is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
 - * License along with Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
@@@ -138,6 -138,7 +138,7 @@@ void avcodec_align_dimensions2(AVCodecC
      case PIX_FMT_YUV422P:
      case PIX_FMT_YUV440P:
      case PIX_FMT_YUV444P:
+     case PIX_FMT_GBRP:
      case PIX_FMT_GRAY8:
      case PIX_FMT_GRAY16BE:
      case PIX_FMT_GRAY16LE:
      case PIX_FMT_YUV444P9BE:
      case PIX_FMT_YUV444P10LE:
      case PIX_FMT_YUV444P10BE:
-     case PIX_FMT_GBR24P:
+     case PIX_FMT_GBRP9LE:
+     case PIX_FMT_GBRP9BE:
+     case PIX_FMT_GBRP10LE:
+     case PIX_FMT_GBRP10BE:
          w_align= 16; //FIXME check for non mpeg style codecs and use less alignment
          h_align= 16;
 -        if(s->codec_id == CODEC_ID_MPEG2VIDEO || s->codec_id == CODEC_ID_MJPEG || s->codec_id == CODEC_ID_AMV || s->codec_id == CODEC_ID_THP || s->codec_id == CODEC_ID_H264)
 +        if(s->codec_id == CODEC_ID_MPEG2VIDEO || s->codec_id == CODEC_ID_MJPEG || s->codec_id == CODEC_ID_AMV || s->codec_id == CODEC_ID_THP || s->codec_id == CODEC_ID_H264 || s->codec_id == CODEC_ID_PRORES)
              h_align= 32; // interlaced is rounded up to 2 MBs
          break;
      case PIX_FMT_YUV411P:
  #if HAVE_MMX
      if(s->codec_id == CODEC_ID_SVQ1 || s->codec_id == CODEC_ID_VP5 ||
         s->codec_id == CODEC_ID_VP6 || s->codec_id == CODEC_ID_VP6F ||
 -       s->codec_id == CODEC_ID_VP6A) {
 +       s->codec_id == CODEC_ID_VP6A || s->codec_id == CODEC_ID_DIRAC) {
          linesize_align[0] =
          linesize_align[1] =
          linesize_align[2] = 16;
@@@ -236,22 -240,6 +240,22 @@@ void avcodec_align_dimensions(AVCodecCo
      *width=FFALIGN(*width, align);
  }
  
 +void ff_init_buffer_info(AVCodecContext *s, AVFrame *pic)
 +{
 +    if (s->pkt) {
 +        pic->pkt_pts = s->pkt->pts;
 +        pic->pkt_pos = s->pkt->pos;
 +    } else {
 +        pic->pkt_pts = AV_NOPTS_VALUE;
 +        pic->pkt_pos = -1;
 +    }
 +    pic->reordered_opaque= s->reordered_opaque;
 +    pic->sample_aspect_ratio = s->sample_aspect_ratio;
 +    pic->width               = s->width;
 +    pic->height              = s->height;
 +    pic->format              = s->pix_fmt;
 +}
 +
  int avcodec_default_get_buffer(AVCodecContext *s, AVFrame *pic){
      int i;
      int w= s->width;
      }
      avci->buffer_count++;
  
 -    if(s->pkt) pic->pkt_pts= s->pkt->pts;
 -    else       pic->pkt_pts= AV_NOPTS_VALUE;
 +    if (s->pkt) {
 +        pic->pkt_pts = s->pkt->pts;
 +        pic->pkt_pos = s->pkt->pos;
 +    } else {
 +        pic->pkt_pts = AV_NOPTS_VALUE;
 +        pic->pkt_pos = -1;
 +    }
      pic->reordered_opaque= s->reordered_opaque;
 +    pic->sample_aspect_ratio = s->sample_aspect_ratio;
 +    pic->width               = s->width;
 +    pic->height              = s->height;
 +    pic->format              = s->pix_fmt;
  
      if(s->debug&FF_DEBUG_BUFFERS)
          av_log(s, AV_LOG_DEBUG, "default_get_buffer called on pic %p, %d "
@@@ -489,11 -468,8 +493,11 @@@ enum PixelFormat avcodec_default_get_fo
  void avcodec_get_frame_defaults(AVFrame *pic){
      memset(pic, 0, sizeof(AVFrame));
  
 -    pic->pts= AV_NOPTS_VALUE;
 +    pic->pts = pic->best_effort_timestamp = AV_NOPTS_VALUE;
 +    pic->pkt_pos = -1;
      pic->key_frame= 1;
 +    pic->sample_aspect_ratio = (AVRational){0, 1};
 +    pic->format = -1;           /* unknown */
  }
  
  AVFrame *avcodec_alloc_frame(void){
      return pic;
  }
  
 +static void avcodec_get_subtitle_defaults(AVSubtitle *sub)
 +{
 +    memset(sub, 0, sizeof(*sub));
 +    sub->pts = AV_NOPTS_VALUE;
 +}
 +
  #if FF_API_AVCODEC_OPEN
  int attribute_align_arg avcodec_open(AVCodecContext *avctx, AVCodec *codec)
  {
@@@ -611,22 -581,13 +615,22 @@@ int attribute_align_arg avcodec_open2(A
  
      av_log(avctx, AV_LOG_DEBUG, "err{or,}_recognition separate: %d; %d\n",
             avctx->error_recognition, avctx->err_recognition);
 -    /* FF_ER_CAREFUL (==1) implies AV_EF_CRCCHECK (== 1<<1 - 1),
 -       FF_ER_COMPLIANT (==2) implies AV_EF_{CRCCHECK,BITSTREAM} (== 1<<2 - 1), et cetera} */
 -    avctx->err_recognition |= (1<<(avctx->error_recognition-(avctx->error_recognition>=FF_ER_VERY_AGGRESSIVE))) - 1;
 +    switch(avctx->error_recognition){
 +        case FF_ER_EXPLODE        : avctx->err_recognition |= AV_EF_EXPLODE | AV_EF_COMPLIANT | AV_EF_CAREFUL;
 +            break;
 +        case FF_ER_VERY_AGGRESSIVE:
 +        case FF_ER_AGGRESSIVE     : avctx->err_recognition |= AV_EF_AGGRESSIVE;
 +        case FF_ER_COMPLIANT      : avctx->err_recognition |= AV_EF_COMPLIANT;
 +        case FF_ER_CAREFUL        : avctx->err_recognition |= AV_EF_CAREFUL;
 +    }
 +
      av_log(avctx, AV_LOG_DEBUG, "err{or,}_recognition combined: %d; %d\n",
             avctx->error_recognition, avctx->err_recognition);
  #endif
  
 +    if (!HAVE_THREADS)
 +        av_log(avctx, AV_LOG_WARNING, "Warning: not compiled with thread support, using thread emulation\n");
 +
      if (HAVE_THREADS && !avctx->thread_opaque) {
          ret = ff_thread_init(avctx);
          if (ret < 0) {
          }
      }
  
 -    if (avctx->codec->max_lowres < avctx->lowres) {
 +    if (avctx->codec->max_lowres < avctx->lowres || avctx->lowres < 0) {
          av_log(avctx, AV_LOG_ERROR, "The maximum value for lowres supported by the decoder is %d\n",
                 avctx->codec->max_lowres);
          ret = AVERROR(EINVAL);
          }
      }
  
 +    avctx->pts_correction_num_faulty_pts =
 +    avctx->pts_correction_num_faulty_dts = 0;
 +    avctx->pts_correction_last_pts =
 +    avctx->pts_correction_last_dts = INT64_MIN;
 +
      if(avctx->codec->init && !(avctx->active_thread_type&FF_THREAD_FRAME)){
          ret = avctx->codec->init(avctx);
          if (ret < 0) {
              goto free_and_end;
          }
      }
 +
 +    ret=0;
  end:
      entangled_thread_counter--;
  
@@@ -763,44 -717,13 +767,44 @@@ int avcodec_encode_subtitle(AVCodecCont
          av_log(avctx, AV_LOG_ERROR, "start_display_time must be 0.\n");
          return -1;
      }
 -    if(sub->num_rects == 0 || !sub->rects)
 -        return -1;
 +
      ret = avctx->codec->encode(avctx, buf, buf_size, sub);
      avctx->frame_number++;
      return ret;
  }
  
 +/**
 + * Attempt to guess proper monotonic timestamps for decoded video frames
 + * which might have incorrect times. Input timestamps may wrap around, in
 + * which case the output will as well.
 + *
 + * @param pts the pts field of the decoded AVPacket, as passed through
 + * AVFrame.pkt_pts
 + * @param dts the dts field of the decoded AVPacket
 + * @return one of the input values, may be AV_NOPTS_VALUE
 + */
 +static int64_t guess_correct_pts(AVCodecContext *ctx,
 +                                 int64_t reordered_pts, int64_t dts)
 +{
 +    int64_t pts = AV_NOPTS_VALUE;
 +
 +    if (dts != AV_NOPTS_VALUE) {
 +        ctx->pts_correction_num_faulty_dts += dts <= ctx->pts_correction_last_dts;
 +        ctx->pts_correction_last_dts = dts;
 +    }
 +    if (reordered_pts != AV_NOPTS_VALUE) {
 +        ctx->pts_correction_num_faulty_pts += reordered_pts <= ctx->pts_correction_last_pts;
 +        ctx->pts_correction_last_pts = reordered_pts;
 +    }
 +    if ((ctx->pts_correction_num_faulty_pts<=ctx->pts_correction_num_faulty_dts || dts == AV_NOPTS_VALUE)
 +       && reordered_pts != AV_NOPTS_VALUE)
 +        pts = reordered_pts;
 +    else
 +        pts = dts;
 +
 +    return pts;
 +}
 +
  int attribute_align_arg avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture,
                           int *got_picture_ptr,
                           AVPacket *avpkt)
      if((avctx->coded_width||avctx->coded_height) && av_image_check_size(avctx->coded_width, avctx->coded_height, 0, avctx))
          return -1;
  
 -    avctx->pkt = avpkt;
 -
      if((avctx->codec->capabilities & CODEC_CAP_DELAY) || avpkt->size || (avctx->active_thread_type&FF_THREAD_FRAME)){
 +        av_packet_split_side_data(avpkt);
 +        avctx->pkt = avpkt;
          if (HAVE_THREADS && avctx->active_thread_type&FF_THREAD_FRAME)
               ret = ff_thread_decode_frame(avctx, picture, got_picture_ptr,
                                            avpkt);
              ret = avctx->codec->decode(avctx, picture, got_picture_ptr,
                                avpkt);
              picture->pkt_dts= avpkt->dts;
 +
 +            if(!avctx->has_b_frames){
 +            picture->pkt_pos= avpkt->pos;
 +            }
 +            //FIXME these should be under if(!avctx->has_b_frames)
 +            if (!picture->sample_aspect_ratio.num)
 +                picture->sample_aspect_ratio = avctx->sample_aspect_ratio;
 +            if (!picture->width)
 +                picture->width = avctx->width;
 +            if (!picture->height)
 +                picture->height = avctx->height;
 +            if (picture->format == PIX_FMT_NONE)
 +                picture->format = avctx->pix_fmt;
          }
  
          emms_c(); //needed to avoid an emms_c() call before every return;
  
 -        if (*got_picture_ptr)
 +
 +        if (*got_picture_ptr){
              avctx->frame_number++;
 +            picture->best_effort_timestamp = guess_correct_pts(avctx,
 +                                                            picture->pkt_pts,
 +                                                            picture->pkt_dts);
 +        }
      }else
          ret= 0;
  
@@@ -893,7 -798,6 +897,7 @@@ int avcodec_decode_subtitle2(AVCodecCon
  
      avctx->pkt = avpkt;
      *got_sub_ptr = 0;
 +    avcodec_get_subtitle_defaults(sub);
      ret = avctx->codec->decode(avctx, sub, got_sub_ptr, avpkt);
      if (*got_sub_ptr)
          avctx->frame_number++;
@@@ -959,21 -863,10 +963,21 @@@ av_cold int avcodec_close(AVCodecContex
      return 0;
  }
  
 +static enum CodecID remap_deprecated_codec_id(enum CodecID id)
 +{
 +    switch(id){
 +        case CODEC_ID_G723_1_DEPRECATED : return CODEC_ID_G723_1;
 +        case CODEC_ID_G729_DEPRECATED   : return CODEC_ID_G729;
 +        case CODEC_ID_UTVIDEO_DEPRECATED: return CODEC_ID_UTVIDEO;
 +        default                         : return id;
 +    }
 +}
 +
  AVCodec *avcodec_find_encoder(enum CodecID id)
  {
      AVCodec *p, *experimental=NULL;
      p = first_avcodec;
 +    id= remap_deprecated_codec_id(id);
      while (p) {
          if (p->encode != NULL && p->id == id) {
              if (p->capabilities & CODEC_CAP_EXPERIMENTAL && !experimental) {
@@@ -1002,19 -895,14 +1006,19 @@@ AVCodec *avcodec_find_encoder_by_name(c
  
  AVCodec *avcodec_find_decoder(enum CodecID id)
  {
 -    AVCodec *p;
 +    AVCodec *p, *experimental=NULL;
      p = first_avcodec;
 +    id= remap_deprecated_codec_id(id);
      while (p) {
 -        if (p->decode != NULL && p->id == id)
 -            return p;
 +        if (p->decode != NULL && p->id == id) {
 +            if (p->capabilities & CODEC_CAP_EXPERIMENTAL && !experimental) {
 +                experimental = p;
 +            } else
 +                return p;
 +        }
          p = p->next;
      }
 -    return NULL;
 +    return experimental;
  }
  
  AVCodec *avcodec_find_decoder_by_name(const char *name)
@@@ -1054,25 -942,6 +1058,25 @@@ static int get_bit_rate(AVCodecContext 
      return bit_rate;
  }
  
 +const char *avcodec_get_name(enum CodecID id)
 +{
 +    AVCodec *codec;
 +
 +#if !CONFIG_SMALL
 +    switch (id) {
 +#include "libavcodec/codec_names.h"
 +    }
 +    av_log(NULL, AV_LOG_WARNING, "Codec 0x%x is not in the full list.\n", id);
 +#endif
 +    codec = avcodec_find_decoder(id);
 +    if (codec)
 +        return codec->name;
 +    codec = avcodec_find_encoder(id);
 +    if (codec)
 +        return codec->name;
 +    return "unknown_codec";
 +}
 +
  size_t av_get_codec_tag_string(char *buf, size_t buf_size, unsigned int codec_tag)
  {
      int i, len, ret = 0;
  
  void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode)
  {
 +    const char *codec_type;
      const char *codec_name;
      const char *profile = NULL;
      AVCodec *p;
 -    char buf1[32];
      int bitrate;
      AVRational display_aspect_ratio;
  
 -    if (encode)
 -        p = avcodec_find_encoder(enc->codec_id);
 -    else
 -        p = avcodec_find_decoder(enc->codec_id);
 -
 -    if (p) {
 -        codec_name = p->name;
 -        profile = av_get_profile_name(p, enc->profile);
 -    } else if (enc->codec_id == CODEC_ID_MPEG2TS) {
 -        /* fake mpeg2 transport stream codec (currently not
 -           registered) */
 -        codec_name = "mpeg2ts";
 -    } else if (enc->codec_name[0] != '\0') {
 -        codec_name = enc->codec_name;
 -    } else {
 -        /* output avi tags */
 +    if (!buf || buf_size <= 0)
 +        return;
 +    codec_type = av_get_media_type_string(enc->codec_type);
 +    codec_name = avcodec_get_name(enc->codec_id);
 +    if (enc->profile != FF_PROFILE_UNKNOWN) {
 +        p = encode ? avcodec_find_encoder(enc->codec_id) :
 +                     avcodec_find_decoder(enc->codec_id);
 +        if (p)
 +            profile = av_get_profile_name(p, enc->profile);
 +    }
 +
 +    snprintf(buf, buf_size, "%s: %s%s", codec_type ? codec_type : "unknown",
 +             codec_name, enc->mb_decision ? " (hq)" : "");
 +    buf[0] ^= 'a' ^ 'A'; /* first letter in uppercase */
 +    if (profile)
 +        snprintf(buf + strlen(buf), buf_size - strlen(buf), " (%s)", profile);
 +    if (enc->codec_tag) {
          char tag_buf[32];
          av_get_codec_tag_string(tag_buf, sizeof(tag_buf), enc->codec_tag);
 -        snprintf(buf1, sizeof(buf1), "%s / 0x%04X", tag_buf, enc->codec_tag);
 -        codec_name = buf1;
 +        snprintf(buf + strlen(buf), buf_size - strlen(buf),
 +                 " (%s / 0x%04X)", tag_buf, enc->codec_tag);
      }
 -
      switch(enc->codec_type) {
      case AVMEDIA_TYPE_VIDEO:
 -        snprintf(buf, buf_size,
 -                 "Video: %s%s",
 -                 codec_name, enc->mb_decision ? " (hq)" : "");
 -        if (profile)
 -            snprintf(buf + strlen(buf), buf_size - strlen(buf),
 -                     " (%s)", profile);
          if (enc->pix_fmt != PIX_FMT_NONE) {
              snprintf(buf + strlen(buf), buf_size - strlen(buf),
                       ", %s",
                            enc->height*enc->sample_aspect_ratio.den,
                            1024*1024);
                  snprintf(buf + strlen(buf), buf_size - strlen(buf),
 -                         " [PAR %d:%d DAR %d:%d]",
 +                         " [SAR %d:%d DAR %d:%d]",
                           enc->sample_aspect_ratio.num, enc->sample_aspect_ratio.den,
                           display_aspect_ratio.num, display_aspect_ratio.den);
              }
          }
          break;
      case AVMEDIA_TYPE_AUDIO:
 -        snprintf(buf, buf_size,
 -                 "Audio: %s",
 -                 codec_name);
 -        if (profile)
 -            snprintf(buf + strlen(buf), buf_size - strlen(buf),
 -                     " (%s)", profile);
          if (enc->sample_rate) {
              snprintf(buf + strlen(buf), buf_size - strlen(buf),
                       ", %d Hz", enc->sample_rate);
                       ", %s", av_get_sample_fmt_name(enc->sample_fmt));
          }
          break;
 -    case AVMEDIA_TYPE_DATA:
 -        snprintf(buf, buf_size, "Data: %s", codec_name);
 -        break;
 -    case AVMEDIA_TYPE_SUBTITLE:
 -        snprintf(buf, buf_size, "Subtitle: %s", codec_name);
 -        break;
 -    case AVMEDIA_TYPE_ATTACHMENT:
 -        snprintf(buf, buf_size, "Attachment: %s", codec_name);
 -        break;
      default:
 -        snprintf(buf, buf_size, "Invalid Codec type %d", enc->codec_type);
          return;
      }
      if (encode) {
@@@ -1202,13 -1093,13 +1206,13 @@@ unsigned avcodec_version( void 
  
  const char *avcodec_configuration(void)
  {
 -    return LIBAV_CONFIGURATION;
 +    return FFMPEG_CONFIGURATION;
  }
  
  const char *avcodec_license(void)
  {
  #define LICENSE_PREFIX "libavcodec license: "
 -    return LICENSE_PREFIX LIBAV_LICENSE + sizeof(LICENSE_PREFIX) - 1;
 +    return LICENSE_PREFIX FFMPEG_LICENSE + sizeof(LICENSE_PREFIX) - 1;
  }
  
  void avcodec_flush_buffers(AVCodecContext *avctx)
@@@ -1329,7 -1220,7 +1333,7 @@@ int ff_match_2uint16(const uint16_t (*t
  
  void av_log_missing_feature(void *avc, const char *feature, int want_sample)
  {
 -    av_log(avc, AV_LOG_WARNING, "%s not implemented. Update your Libav "
 +    av_log(avc, AV_LOG_WARNING, "%s not implemented. Update your FFmpeg "
              "version to the newest one from Git. If the problem still "
              "occurs, it means that your file has a feature which has not "
              "been implemented.\n", feature);
@@@ -1346,8 -1237,8 +1350,8 @@@ void av_log_ask_for_sample(void *avc, c
      if (msg)
          av_vlog(avc, AV_LOG_WARNING, msg, argument_list);
      av_log(avc, AV_LOG_WARNING, "If you want to help, upload a sample "
 -            "of this file to ftp://upload.libav.org/incoming/ "
 -            "and contact the libav-devel mailing list.\n");
 +            "of this file to ftp://upload.ffmpeg.org/MPlayer/incoming/ "
 +            "and contact the ffmpeg-devel mailing list.\n");
  
      va_end(argument_list);
  }
@@@ -1431,9 -1322,6 +1435,9 @@@ unsigned int avpriv_toupper4(unsigned i
  int ff_thread_get_buffer(AVCodecContext *avctx, AVFrame *f)
  {
      f->owner = avctx;
 +
 +    ff_init_buffer_info(avctx, f);
 +
      return avctx->get_buffer(avctx, f);
  }
  
@@@ -1466,12 -1354,6 +1470,12 @@@ int avcodec_thread_init(AVCodecContext 
  
  enum AVMediaType avcodec_get_type(enum CodecID codec_id)
  {
 +    AVCodec *c= avcodec_find_decoder(codec_id);
 +    if(!c)
 +        c= avcodec_find_encoder(codec_id);
 +    if(c)
 +        return c->type;
 +
      if (codec_id <= CODEC_ID_NONE)
          return AVMEDIA_TYPE_UNKNOWN;
      else if (codec_id < CODEC_ID_FIRST_AUDIO)
diff --combined libavcodec/version.h
index 591d419d26a38e0595a6a87f88dbbf6e15b75f05,6280e1c1c96256a10519801294772c7b609699b2..f3de82b193d5eedcc116c6046f0462cf048bc728
@@@ -1,19 -1,19 +1,19 @@@
  /*
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * FFmpeg is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 2.1 of the License, or (at your option) any later version.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * FFmpeg is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
 - * License along with Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
@@@ -21,7 -21,7 +21,7 @@@
  #define AVCODEC_VERSION_H
  
  #define LIBAVCODEC_VERSION_MAJOR 53
 -#define LIBAVCODEC_VERSION_MINOR 22
 +#define LIBAVCODEC_VERSION_MINOR 37
  #define LIBAVCODEC_VERSION_MICRO  0
  
  #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
  #ifndef FF_API_INTERNAL_CONTEXT
  #define FF_API_INTERNAL_CONTEXT (LIBAVCODEC_VERSION_MAJOR < 54)
  #endif
+ #ifndef FF_API_TIFFENC_COMPLEVEL
+ #define FF_API_TIFFENC_COMPLEVEL (LIBAVCODEC_VERSION_MAJOR < 54)
+ #endif
  
  #endif /* AVCODEC_VERSION_H */
diff --combined libavutil/avutil.h
index 37418b5883660fdd15490706ef543c36336e038a,a2d3073467151dc291c4a55093ad96b86333784d..a09fe9417b46a5c185e3d3276b615bd46600d986
@@@ -1,20 -1,20 +1,20 @@@
  /*
   * copyright (c) 2006 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.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * FFmpeg is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
 - * License along with Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
   */
  
  #define LIBAVUTIL_VERSION_MAJOR 51
- #define LIBAVUTIL_VERSION_MINOR 28
 -#define LIBAVUTIL_VERSION_MINOR 19
++#define LIBAVUTIL_VERSION_MINOR 29
  #define LIBAVUTIL_VERSION_MICRO  0
  
  #define LIBAVUTIL_VERSION_INT   AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \
   *
   * @{
   */
 +#ifndef FF_API_OLD_EVAL_NAMES
 +#define FF_API_OLD_EVAL_NAMES (LIBAVUTIL_VERSION_MAJOR < 52)
 +#endif
  #ifndef FF_API_GET_BITS_PER_SAMPLE_FMT
  #define FF_API_GET_BITS_PER_SAMPLE_FMT (LIBAVUTIL_VERSION_MAJOR < 52)
  #endif
@@@ -237,12 -234,6 +237,12 @@@ enum AVMediaType 
      AVMEDIA_TYPE_NB
  };
  
 +/**
 + * Return a string describing the media_type enum, NULL if media_type
 + * is unknown.
 + */
 +const char *av_get_media_type_string(enum AVMediaType media_type);
 +
  /**
   * @defgroup lavu_const Constants
   * @{
   */
  
  enum AVPictureType {
 -    AV_PICTURE_TYPE_I = 1, ///< Intra
 +    AV_PICTURE_TYPE_NONE = 0, ///< Undefined
 +    AV_PICTURE_TYPE_I,     ///< Intra
      AV_PICTURE_TYPE_P,     ///< Predicted
      AV_PICTURE_TYPE_B,     ///< Bi-dir predicted
      AV_PICTURE_TYPE_S,     ///< S(GMC)-VOP MPEG4
@@@ -324,21 -314,8 +324,21 @@@ char av_get_picture_type_char(enum AVPi
   * @}
   */
  
 +/**
 + * Return x default pointer in case p is NULL.
 + */
 +static inline const void *av_x_if_null(const void *p, const void *x)
 +{
 +    return p ? p : x;
 +}
 +
  #include "common.h"
  #include "error.h"
 +#include "mathematics.h"
 +#include "rational.h"
 +#include "intfloat_readwrite.h"
 +#include "log.h"
 +#include "pixfmt.h"
  
  /**
   * @}
diff --combined libavutil/pixdesc.c
index 958499db9d9095eeab340db09e911fb4b1a8260a,3a830ba3de2600feabde4312cce326bfa2b7618a..1d3cfdfedcf456fa59474dd0b70a1a3e8539e2aa
@@@ -2,20 -2,20 +2,20 @@@
   * pixel format descriptor
   * Copyright (c) 2009 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.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * FFmpeg is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
 - * License along with Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
@@@ -126,6 -126,7 +126,7 @@@ const AVPixFmtDescriptor av_pix_fmt_des
              {1,0,1,0,7},        /* U */
              {2,0,1,0,7},        /* V */
          },
+         .flags = PIX_FMT_PLANAR,
      },
      [PIX_FMT_YUYV422] = {
          .name = "yuyv422",
              {0,2,2,0,7},        /* G */
              {0,2,3,0,7},        /* B */
          },
+         .flags = PIX_FMT_RGB,
      },
      [PIX_FMT_BGR24] = {
          .name = "bgr24",
              {0,2,2,0,7},        /* G */
              {0,2,3,0,7},        /* R */
          },
+         .flags = PIX_FMT_RGB,
      },
      [PIX_FMT_YUV422P] = {
          .name = "yuv422p",
              {1,0,1,0,7},        /* U */
              {2,0,1,0,7},        /* V */
          },
+         .flags = PIX_FMT_PLANAR,
      },
      [PIX_FMT_YUV444P] = {
          .name = "yuv444p",
              {1,0,1,0,7},        /* U */
              {2,0,1,0,7},        /* V */
          },
+         .flags = PIX_FMT_PLANAR,
      },
      [PIX_FMT_YUV410P] = {
          .name = "yuv410p",
              {1,0,1,0,7},        /* U */
              {2,0,1,0,7},        /* V */
          },
+         .flags = PIX_FMT_PLANAR,
      },
      [PIX_FMT_YUV411P] = {
          .name = "yuv411p",
              {1,0,1,0,7},        /* U */
              {2,0,1,0,7},        /* V */
          },
+         .flags = PIX_FMT_PLANAR,
      },
      [PIX_FMT_GRAY8] = {
          .name = "gray",
          .comp = {
              {0,0,1,0,7},        /* Y */
          },
-         .flags = PIX_FMT_PAL,
      },
      [PIX_FMT_MONOWHITE] = {
          .name = "monow",
              {1,0,1,0,7},        /* U */
              {2,0,1,0,7},        /* V */
          },
+         .flags = PIX_FMT_PLANAR,
      },
      [PIX_FMT_YUVJ422P] = {
          .name = "yuvj422p",
              {1,0,1,0,7},        /* U */
              {2,0,1,0,7},        /* V */
          },
+         .flags = PIX_FMT_PLANAR,
      },
      [PIX_FMT_YUVJ444P] = {
          .name = "yuvj444p",
              {1,0,1,0,7},        /* U */
              {2,0,1,0,7},        /* V */
          },
+         .flags = PIX_FMT_PLANAR,
      },
      [PIX_FMT_XVMC_MPEG2_MC] = {
          .name = "xvmcmc",
              {0,0,1,3,2},        /* G */
              {0,0,1,0,2},        /* R */
          },
-         .flags = PIX_FMT_PAL,
+         .flags = PIX_FMT_PAL | PIX_FMT_RGB,
      },
      [PIX_FMT_BGR4] = {
          .name = "bgr4",
              {0,3,2,0,1},        /* G */
              {0,3,4,0,0},        /* R */
          },
-         .flags = PIX_FMT_BITSTREAM,
+         .flags = PIX_FMT_BITSTREAM | PIX_FMT_RGB,
      },
      [PIX_FMT_BGR4_BYTE] = {
          .name = "bgr4_byte",
              {0,0,1,1,1},        /* G */
              {0,0,1,0,0},        /* R */
          },
-         .flags = PIX_FMT_PAL,
+         .flags = PIX_FMT_PAL | PIX_FMT_RGB,
      },
      [PIX_FMT_RGB8] = {
          .name = "rgb8",
              {0,0,1,3,2},        /* G */
              {0,0,1,0,2},        /* B */
          },
-         .flags = PIX_FMT_PAL,
+         .flags = PIX_FMT_PAL | PIX_FMT_RGB,
      },
      [PIX_FMT_RGB4] = {
          .name = "rgb4",
              {0,3,2,0,1},       /* G */
              {0,3,4,0,0},       /* B */
          },
-         .flags = PIX_FMT_BITSTREAM,
+         .flags = PIX_FMT_BITSTREAM | PIX_FMT_RGB,
      },
      [PIX_FMT_RGB4_BYTE] = {
          .name = "rgb4_byte",
              {0,0,1,1,1},        /* G */
              {0,0,1,0,0},        /* B */
          },
-         .flags = PIX_FMT_PAL,
+         .flags = PIX_FMT_PAL | PIX_FMT_RGB,
      },
      [PIX_FMT_NV12] = {
          .name = "nv12",
              {1,1,1,0,7},        /* U */
              {1,1,2,0,7},        /* V */
          },
+         .flags = PIX_FMT_PLANAR,
      },
      [PIX_FMT_NV21] = {
          .name = "nv21",
              {1,1,1,0,7},        /* V */
              {1,1,2,0,7},        /* U */
          },
+         .flags = PIX_FMT_PLANAR,
      },
      [PIX_FMT_ARGB] = {
          .name = "argb",
              {0,3,3,0,7},        /* G */
              {0,3,4,0,7},        /* B */
          },
+         .flags = PIX_FMT_RGB,
      },
      [PIX_FMT_RGBA] = {
          .name = "rgba",
              {0,3,3,0,7},        /* B */
              {0,3,4,0,7},        /* A */
          },
+         .flags = PIX_FMT_RGB,
      },
      [PIX_FMT_ABGR] = {
          .name = "abgr",
              {0,3,3,0,7},        /* G */
              {0,3,4,0,7},        /* R */
          },
+         .flags = PIX_FMT_RGB,
      },
      [PIX_FMT_BGRA] = {
          .name = "bgra",
              {0,3,3,0,7},        /* R */
              {0,3,4,0,7},        /* A */
          },
+         .flags = PIX_FMT_RGB,
      },
      [PIX_FMT_GRAY16BE] = {
          .name = "gray16be",
              {1,0,1,0,7},        /* U */
              {2,0,1,0,7},        /* V */
          },
+         .flags = PIX_FMT_PLANAR,
      },
      [PIX_FMT_YUVJ440P] = {
          .name = "yuvj440p",
              {1,0,1,0,7},        /* U */
              {2,0,1,0,7},        /* V */
          },
+         .flags = PIX_FMT_PLANAR,
      },
      [PIX_FMT_YUVA420P] = {
          .name = "yuva420p",
              {2,0,1,0,7},        /* V */
              {3,0,1,0,7},        /* A */
          },
+         .flags = PIX_FMT_PLANAR,
      },
      [PIX_FMT_VDPAU_H264] = {
          .name = "vdpau_h264",
              {0,5,3,0,15},       /* G */
              {0,5,5,0,15},       /* B */
          },
-         .flags = PIX_FMT_BE,
+         .flags = PIX_FMT_RGB | PIX_FMT_BE,
      },
      [PIX_FMT_RGB48LE] = {
          .name = "rgb48le",
              {0,5,3,0,15},       /* G */
              {0,5,5,0,15},       /* B */
          },
+         .flags = PIX_FMT_RGB,
      },
-         .flags = PIX_FMT_BE,
 +    [PIX_FMT_RGBA64BE] = {
 +        .name = "rgba64be",
 +        .nb_components= 4,
 +        .log2_chroma_w= 0,
 +        .log2_chroma_h= 0,
 +        .comp = {
 +            {0,5,1,0,15},       /* R */
 +            {0,5,3,0,15},       /* G */
 +            {0,5,5,0,15},       /* B */
 +            {0,5,7,0,15},       /* A */
 +        },
++        .flags = PIX_FMT_RGB | PIX_FMT_BE,
 +    },
 +    [PIX_FMT_RGBA64LE] = {
 +        .name = "rgba64le",
 +        .nb_components= 4,
 +        .log2_chroma_w= 0,
 +        .log2_chroma_h= 0,
 +        .comp = {
 +            {0,5,1,0,15},       /* R */
 +            {0,5,3,0,15},       /* G */
 +            {0,5,5,0,15},       /* B */
 +            {0,5,7,0,15},       /* B */
 +        },
++        .flags = PIX_FMT_RGB,
 +    },
      [PIX_FMT_RGB565BE] = {
          .name = "rgb565be",
          .nb_components= 3,
              {0,1,1,5,5},        /* G */
              {0,1,1,0,4},        /* B */
          },
-         .flags = PIX_FMT_BE,
+         .flags = PIX_FMT_BE | PIX_FMT_RGB,
      },
      [PIX_FMT_RGB565LE] = {
          .name = "rgb565le",
              {0,1,1,5,5},        /* G */
              {0,1,1,0,4},        /* B */
          },
+         .flags = PIX_FMT_RGB,
      },
      [PIX_FMT_RGB555BE] = {
          .name = "rgb555be",
              {0,1,1,5,4},        /* G */
              {0,1,1,0,4},        /* B */
          },
-         .flags = PIX_FMT_BE,
+         .flags = PIX_FMT_BE | PIX_FMT_RGB,
      },
      [PIX_FMT_RGB555LE] = {
          .name = "rgb555le",
              {0,1,1,5,4},        /* G */
              {0,1,1,0,4},        /* B */
          },
+         .flags = PIX_FMT_RGB,
      },
      [PIX_FMT_RGB444BE] = {
          .name = "rgb444be",
              {0,1,1,4,3},        /* G */
              {0,1,1,0,3},        /* B */
          },
-         .flags = PIX_FMT_BE,
+         .flags = PIX_FMT_BE | PIX_FMT_RGB,
      },
      [PIX_FMT_RGB444LE] = {
          .name = "rgb444le",
              {0,1,1,4,3},        /* G */
              {0,1,1,0,3},        /* B */
          },
+         .flags = PIX_FMT_RGB,
      },
      [PIX_FMT_BGR48BE] = {
          .name = "bgr48be",
              {0,5,3,0,15},       /* G */
              {0,5,5,0,15},       /* R */
          },
-         .flags = PIX_FMT_BE,
+         .flags = PIX_FMT_BE | PIX_FMT_RGB,
      },
      [PIX_FMT_BGR48LE] = {
          .name = "bgr48le",
              {0,5,3,0,15},       /* G */
              {0,5,5,0,15},       /* R */
          },
+         .flags = PIX_FMT_RGB,
      },
 +    [PIX_FMT_BGRA64BE] = {
 +        .name = "bgra64be",
 +        .nb_components= 4,
 +        .log2_chroma_w= 0,
 +        .log2_chroma_h= 0,
 +        .comp = {
 +            {0,5,1,0,15},       /* B */
 +            {0,5,3,0,15},       /* G */
 +            {0,5,5,0,15},       /* R */
 +            {0,5,7,0,15},       /* A */
 +        },
 +        .flags = PIX_FMT_BE,
 +    },
 +    [PIX_FMT_BGRA64LE] = {
 +        .name = "bgra64le",
 +        .nb_components= 4,
 +        .log2_chroma_w= 0,
 +        .log2_chroma_h= 0,
 +        .comp = {
 +            {0,5,1,0,15},       /* B */
 +            {0,5,3,0,15},       /* G */
 +            {0,5,5,0,15},       /* R */
 +            {0,5,7,0,15},       /* A */
 +        },
 +    },
      [PIX_FMT_BGR565BE] = {
          .name = "bgr565be",
          .nb_components= 3,
              {0,1,1,5,5},        /* G */
              {0,1,1,0,4},        /* R */
          },
-         .flags = PIX_FMT_BE,
+         .flags = PIX_FMT_BE | PIX_FMT_RGB,
      },
      [PIX_FMT_BGR565LE] = {
          .name = "bgr565le",
              {0,1,1,5,5},        /* G */
              {0,1,1,0,4},        /* R */
          },
+         .flags = PIX_FMT_RGB,
      },
      [PIX_FMT_BGR555BE] = {
          .name = "bgr555be",
              {0,1,1,5,4},       /* G */
              {0,1,1,0,4},       /* R */
          },
-         .flags = PIX_FMT_BE,
+         .flags = PIX_FMT_BE | PIX_FMT_RGB,
       },
      [PIX_FMT_BGR555LE] = {
          .name = "bgr555le",
              {0,1,1,5,4},        /* G */
              {0,1,1,0,4},        /* R */
          },
+         .flags = PIX_FMT_RGB,
      },
      [PIX_FMT_BGR444BE] = {
          .name = "bgr444be",
              {0,1,1,4,3},       /* G */
              {0,1,1,0,3},       /* R */
          },
-         .flags = PIX_FMT_BE,
+         .flags = PIX_FMT_BE | PIX_FMT_RGB,
       },
      [PIX_FMT_BGR444LE] = {
          .name = "bgr444le",
              {0,1,1,4,3},        /* G */
              {0,1,1,0,3},        /* R */
          },
+         .flags = PIX_FMT_RGB,
      },
      [PIX_FMT_VAAPI_MOCO] = {
          .name = "vaapi_moco",
              {1,1,1,0,8},        /* U */
              {2,1,1,0,8},        /* V */
          },
+         .flags = PIX_FMT_PLANAR,
      },
      [PIX_FMT_YUV420P9BE] = {
          .name = "yuv420p9be",
              {1,1,1,0,8},        /* U */
              {2,1,1,0,8},        /* V */
          },
-         .flags = PIX_FMT_BE,
+         .flags = PIX_FMT_BE | PIX_FMT_PLANAR,
      },
      [PIX_FMT_YUV420P10LE] = {
          .name = "yuv420p10le",
              {1,1,1,0,9},        /* U */
              {2,1,1,0,9},        /* V */
          },
+         .flags = PIX_FMT_PLANAR,
      },
      [PIX_FMT_YUV420P10BE] = {
          .name = "yuv420p10be",
              {1,1,1,0,9},        /* U */
              {2,1,1,0,9},        /* V */
          },
-         .flags = PIX_FMT_BE,
+         .flags = PIX_FMT_BE | PIX_FMT_PLANAR,
      },
      [PIX_FMT_YUV420P16LE] = {
          .name = "yuv420p16le",
              {1,1,1,0,15},        /* U */
              {2,1,1,0,15},        /* V */
          },
+         .flags = PIX_FMT_PLANAR,
      },
      [PIX_FMT_YUV420P16BE] = {
          .name = "yuv420p16be",
              {1,1,1,0,15},        /* U */
              {2,1,1,0,15},        /* V */
          },
-         .flags = PIX_FMT_BE,
+         .flags = PIX_FMT_BE | PIX_FMT_PLANAR,
      },
      [PIX_FMT_YUV422P9LE] = {
          .name = "yuv422p9le",
              {1,1,1,0,8},        /* U */
              {2,1,1,0,8},        /* V */
          },
+         .flags = PIX_FMT_PLANAR,
      },
      [PIX_FMT_YUV422P9BE] = {
          .name = "yuv422p9be",
              {1,1,1,0,8},        /* U */
              {2,1,1,0,8},        /* V */
          },
-         .flags = PIX_FMT_BE,
+         .flags = PIX_FMT_BE | PIX_FMT_PLANAR,
      },
      [PIX_FMT_YUV422P10LE] = {
          .name = "yuv422p10le",
              {1,1,1,0,9},        /* U */
              {2,1,1,0,9},        /* V */
          },
+         .flags = PIX_FMT_PLANAR,
      },
      [PIX_FMT_YUV422P10BE] = {
          .name = "yuv422p10be",
              {1,1,1,0,9},        /* U */
              {2,1,1,0,9},        /* V */
          },
-         .flags = PIX_FMT_BE,
+         .flags = PIX_FMT_BE | PIX_FMT_PLANAR,
      },
      [PIX_FMT_YUV422P16LE] = {
          .name = "yuv422p16le",
              {1,1,1,0,15},        /* U */
              {2,1,1,0,15},        /* V */
          },
+         .flags = PIX_FMT_PLANAR,
      },
      [PIX_FMT_YUV422P16BE] = {
          .name = "yuv422p16be",
              {1,1,1,0,15},        /* U */
              {2,1,1,0,15},        /* V */
          },
-         .flags = PIX_FMT_BE,
+         .flags = PIX_FMT_BE | PIX_FMT_PLANAR,
      },
      [PIX_FMT_YUV444P16LE] = {
          .name = "yuv444p16le",
              {1,1,1,0,15},        /* U */
              {2,1,1,0,15},        /* V */
          },
+         .flags = PIX_FMT_PLANAR,
      },
      [PIX_FMT_YUV444P16BE] = {
          .name = "yuv444p16be",
              {1,1,1,0,15},        /* U */
              {2,1,1,0,15},        /* V */
          },
-         .flags = PIX_FMT_BE,
+         .flags = PIX_FMT_BE | PIX_FMT_PLANAR,
      },
      [PIX_FMT_YUV444P10LE] = {
          .name = "yuv444p10le",
              {1,1,1,0,9},        /* U */
              {2,1,1,0,9},        /* V */
          },
+         .flags = PIX_FMT_PLANAR,
      },
      [PIX_FMT_YUV444P10BE] = {
          .name = "yuv444p10be",
              {1,1,1,0,9},        /* U */
              {2,1,1,0,9},        /* V */
          },
-         .flags = PIX_FMT_BE,
+         .flags = PIX_FMT_BE | PIX_FMT_PLANAR,
      },
      [PIX_FMT_YUV444P9LE] = {
          .name = "yuv444p9le",
              {1,1,1,0,8},        /* U */
              {2,1,1,0,8},        /* V */
          },
+         .flags = PIX_FMT_PLANAR,
      },
      [PIX_FMT_YUV444P9BE] = {
          .name = "yuv444p9be",
              {1,1,1,0,8},        /* U */
              {2,1,1,0,8},        /* V */
          },
-         .flags = PIX_FMT_BE,
+         .flags = PIX_FMT_BE | PIX_FMT_PLANAR,
      },
      [PIX_FMT_DXVA2_VLD] = {
          .name = "dxva2_vld",
          .log2_chroma_h = 1,
          .flags = PIX_FMT_HWACCEL,
      },
 -    [PIX_FMT_Y400A] = {
 -        .name = "y400a",
 +    [PIX_FMT_VDA_VLD] = {
 +        .name = "vda_vld",
 +        .log2_chroma_w = 1,
 +        .log2_chroma_h = 1,
 +        .flags = PIX_FMT_HWACCEL,
 +    },
 +    [PIX_FMT_GRAY8A] = {
 +        .name = "gray8a",
          .nb_components= 2,
          .comp = {
              {0,1,1,0,7},        /* Y */
              {0,1,2,0,7},        /* A */
          },
      },
 +    [PIX_FMT_GBR24P] = {
 +        .name = "gbr24p",
 +        .nb_components= 3,
 +        .comp = {
 +            {1,0,1,0,7},        /* B */
 +            {0,0,1,0,7},        /* G */
 +            {2,0,1,0,7},        /* R */
 +        },
++        .flags = PIX_FMT_PLANAR | PIX_FMT_RGB,
++    },
+     [PIX_FMT_GBRP] = {
+         .name = "gbrp",
+         .nb_components= 3,
+         .log2_chroma_w= 0,
+         .log2_chroma_h= 0,
+         .comp = {
+             {0,0,1,0,7},        /* G */
+             {1,0,1,0,7},        /* B */
+             {2,0,1,0,7},        /* R */
+         },
+         .flags = PIX_FMT_PLANAR | PIX_FMT_RGB,
+     },
+     [PIX_FMT_GBRP9LE] = {
+         .name = "gbrp9le",
+         .nb_components= 3,
+         .log2_chroma_w= 0,
+         .log2_chroma_h= 0,
+         .comp = {
+             {0,1,1,0,8},        /* G */
+             {1,1,1,0,8},        /* B */
+             {2,1,1,0,8},        /* R */
+         },
+         .flags = PIX_FMT_PLANAR | PIX_FMT_RGB,
+     },
+     [PIX_FMT_GBRP9BE] = {
+         .name = "gbrp9be",
+         .nb_components= 3,
+         .log2_chroma_w= 0,
+         .log2_chroma_h= 0,
+         .comp = {
+             {0,1,1,0,8},        /* G */
+             {1,1,1,0,8},        /* B */
+             {2,1,1,0,8},        /* R */
+         },
+         .flags = PIX_FMT_BE | PIX_FMT_PLANAR | PIX_FMT_RGB,
+     },
+     [PIX_FMT_GBRP10LE] = {
+         .name = "gbrp10le",
+         .nb_components= 3,
+         .log2_chroma_w= 0,
+         .log2_chroma_h= 0,
+         .comp = {
+             {0,1,1,0,9},        /* G */
+             {1,1,1,0,9},        /* B */
+             {2,1,1,0,9},        /* R */
+         },
+         .flags = PIX_FMT_PLANAR | PIX_FMT_RGB,
+     },
+     [PIX_FMT_GBRP10BE] = {
+         .name = "gbrp10be",
+         .nb_components= 3,
+         .log2_chroma_w= 0,
+         .log2_chroma_h= 0,
+         .comp = {
+             {0,1,1,0,9},        /* G */
+             {1,1,1,0,9},        /* B */
+             {2,1,1,0,9},        /* R */
+         },
+         .flags = PIX_FMT_BE | PIX_FMT_PLANAR | PIX_FMT_RGB,
+     },
+     [PIX_FMT_GBRP16LE] = {
+         .name = "gbrp16le",
+         .nb_components= 3,
+         .log2_chroma_w= 0,
+         .log2_chroma_h= 0,
+         .comp = {
+             {0,1,1,0,15},       /* G */
+             {1,1,1,0,15},       /* B */
+             {2,1,1,0,15},       /* R */
+         },
+         .flags = PIX_FMT_PLANAR | PIX_FMT_RGB,
+     },
+     [PIX_FMT_GBRP16BE] = {
+         .name = "gbrp16be",
+         .nb_components= 3,
+         .log2_chroma_w= 0,
+         .log2_chroma_h= 0,
+         .comp = {
+             {0,1,1,0,15},       /* G */
+             {1,1,1,0,15},       /* B */
+             {2,1,1,0,15},       /* R */
+         },
+         .flags = PIX_FMT_BE | PIX_FMT_PLANAR | PIX_FMT_RGB,
      },
  };
  
diff --combined libavutil/pixdesc.h
index f0de9981ec7ab3f39aadeed5c13032d26f6f6b7d,b5972c78ff4f782d4cbc20aeb3fa774f1211efab..217524678593c5732f3f461377c79619571d4964
@@@ -2,20 -2,20 +2,20 @@@
   * pixel format descriptor
   * Copyright (c) 2009 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.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * FFmpeg is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
 - * License along with Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
@@@ -87,6 -87,8 +87,8 @@@ typedef struct AVPixFmtDescriptor
  #define PIX_FMT_PAL       2 ///< Pixel format has a palette in data[1], values are indexes in this palette.
  #define PIX_FMT_BITSTREAM 4 ///< All values of a component are bit-wise packed end to end.
  #define PIX_FMT_HWACCEL   8 ///< Pixel format is an HW accelerated format.
+ #define PIX_FMT_PLANAR   16 ///< At least one pixel component is not in the first data plane
+ #define PIX_FMT_RGB      32 ///< The pixel format contains RGB-like data (as opposed to YUV/grayscale)
  
  /**
   * The array of all the pixel format descriptors.
diff --combined libavutil/pixfmt.h
index f711de78281c3bd9fdde89d4c6a35a582bb3989a,bd898bdc8ed68ad77426ed0d6887f03a0b07cb70..2930a9b68126b7b7aa260345ebc791d3c2068cf1
@@@ -1,20 -1,20 +1,20 @@@
  /*
   * copyright (c) 2006 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.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * FFmpeg is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
 - * License along with Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
@@@ -134,13 -134,9 +134,13 @@@ enum PixelFormat 
      PIX_FMT_RGB444BE,  ///< packed RGB 4:4:4, 16bpp, (msb)4A 4R 4G 4B(lsb), big-endian, most significant bits to 0
      PIX_FMT_BGR444LE,  ///< packed BGR 4:4:4, 16bpp, (msb)4A 4B 4G 4R(lsb), little-endian, most significant bits to 1
      PIX_FMT_BGR444BE,  ///< packed BGR 4:4:4, 16bpp, (msb)4A 4B 4G 4R(lsb), big-endian, most significant bits to 1
 -    PIX_FMT_Y400A,     ///< 8bit gray, 8bit alpha
 +    PIX_FMT_GRAY8A,    ///< 8bit gray, 8bit alpha
      PIX_FMT_BGR48BE,   ///< packed RGB 16:16:16, 48bpp, 16B, 16G, 16R, the 2-byte value for each R/G/B component is stored as big-endian
      PIX_FMT_BGR48LE,   ///< packed RGB 16:16:16, 48bpp, 16B, 16G, 16R, the 2-byte value for each R/G/B component is stored as little-endian
 +
 +    //the following 10 formats have the disadvantage of needing 1 format for each bit depth, thus
 +    //If you want to support multiple bit depths, then using PIX_FMT_YUV420P16* with the bpp stored seperately
 +    //is better
      PIX_FMT_YUV420P9BE, ///< planar YUV 4:2:0, 13.5bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian
      PIX_FMT_YUV420P9LE, ///< planar YUV 4:2:0, 13.5bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian
      PIX_FMT_YUV420P10BE,///< planar YUV 4:2:0, 15bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian
      PIX_FMT_YUV422P9BE, ///< planar YUV 4:2:2, 18bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian
      PIX_FMT_YUV422P9LE, ///< planar YUV 4:2:2, 18bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian
      PIX_FMT_VDA_VLD,    ///< hardware decoding through VDA
-     PIX_FMT_GBR24P,    ///< planar GBR, 24bpp, 8G, 8B, 8R.
 +
++#ifdef AV_PIX_FMT_ABI_GIT_MASTER
 +    PIX_FMT_RGBA64BE,  ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is stored as big-endian
 +    PIX_FMT_RGBA64LE,  ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is stored as little-endian
 +    PIX_FMT_BGRA64BE,  ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G, 16R, 16A, the 2-byte value for each R/G/B/A component is stored as big-endian
 +    PIX_FMT_BGRA64LE,  ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G, 16R, 16A, the 2-byte value for each R/G/B/A component is stored as little-endian
++#endif
+     PIX_FMT_GBRP,      ///< planar GBR 4:4:4 24bpp
+     PIX_FMT_GBRP9BE,   ///< planar GBR 4:4:4 27bpp, big endian
+     PIX_FMT_GBRP9LE,   ///< planar GBR 4:4:4 27bpp, little endian
+     PIX_FMT_GBRP10BE,  ///< planar GBR 4:4:4 30bpp, big endian
+     PIX_FMT_GBRP10LE,  ///< planar GBR 4:4:4 30bpp, little endian
+     PIX_FMT_GBRP16BE,  ///< planar GBR 4:4:4 48bpp, big endian
+     PIX_FMT_GBRP16LE,  ///< planar GBR 4:4:4 48bpp, little endian
++
++#ifndef AV_PIX_FMT_ABI_GIT_MASTER
++    PIX_FMT_RGBA64BE=0x123,  ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is stored as big-endian
++    PIX_FMT_RGBA64LE,  ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is stored as little-endian
++    PIX_FMT_BGRA64BE,  ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G, 16R, 16A, the 2-byte value for each R/G/B/A component is stored as big-endian
++    PIX_FMT_BGRA64LE,  ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G, 16R, 16A, the 2-byte value for each R/G/B/A component is stored as little-endian
++#endif
      PIX_FMT_NB,        ///< number of pixel formats, DO NOT USE THIS if you want to link with shared libav* because the number of formats might differ between versions
  };
  
 +#define PIX_FMT_Y400A PIX_FMT_GRAY8A
++#define PIX_FMT_GBR24P PIX_FMT_GBRP
 +
  #if AV_HAVE_BIGENDIAN
  #   define PIX_FMT_NE(be, le) PIX_FMT_##be
  #else
  #define PIX_FMT_YUV422P16 PIX_FMT_NE(YUV422P16BE, YUV422P16LE)
  #define PIX_FMT_YUV444P16 PIX_FMT_NE(YUV444P16BE, YUV444P16LE)
  
 +#define PIX_FMT_RGBA64 PIX_FMT_NE(RGBA64BE, RGBA64LE)
 +#define PIX_FMT_BGRA64 PIX_FMT_NE(BGRA64BE, BGRA64LE)
+ #define PIX_FMT_GBRP9     PIX_FMT_NE(GBRP9BE ,    GBRP9LE)
+ #define PIX_FMT_GBRP10    PIX_FMT_NE(GBRP10BE,    GBRP10LE)
+ #define PIX_FMT_GBRP16    PIX_FMT_NE(GBRP16BE,    GBRP16LE)
  #endif /* AVUTIL_PIXFMT_H */
diff --combined libswscale/swscale.c
index 4be9b800aedadc2eae1ea1778805ccdbbb0769f2,98daf22cbd910552f1893b51ba41e8ec2cc10ba4..afc510a75c453a810fb05b3effaf369a385938a1
@@@ -1,20 -1,20 +1,20 @@@
  /*
 - * Copyright (C) 2001-2003 Michael Niedermayer <michaelni@gmx.at>
 + * Copyright (C) 2001-2011 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.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * FFmpeg is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
 - * License along with Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
@@@ -60,7 -60,6 +60,7 @@@ untested special converter
  #include "swscale.h"
  #include "swscale_internal.h"
  #include "rgb2rgb.h"
 +#include "libavutil/avassert.h"
  #include "libavutil/intreadwrite.h"
  #include "libavutil/cpu.h"
  #include "libavutil/avutil.h"
@@@ -68,6 -67,7 +68,6 @@@
  #include "libavutil/bswap.h"
  #include "libavutil/pixdesc.h"
  
 -#define DITHER1XBPP
  
  #define RGB2YUV_SHIFT 15
  #define BY ( (int)(0.114*219/255*(1<<RGB2YUV_SHIFT)+0.5))
@@@ -195,101 -195,6 +195,101 @@@ DECLARE_ALIGNED(8, const uint8_t, dithe
  DECLARE_ALIGNED(8, const uint8_t, ff_sws_pb_64)[8] =
  {  64, 64, 64, 64, 64, 64, 64, 64 };
  
 +DECLARE_ALIGNED(8, const uint8_t, dithers)[8][8][8]={
 +{
 +  {   0,  1,  0,  1,  0,  1,  0,  1,},
 +  {   1,  0,  1,  0,  1,  0,  1,  0,},
 +  {   0,  1,  0,  1,  0,  1,  0,  1,},
 +  {   1,  0,  1,  0,  1,  0,  1,  0,},
 +  {   0,  1,  0,  1,  0,  1,  0,  1,},
 +  {   1,  0,  1,  0,  1,  0,  1,  0,},
 +  {   0,  1,  0,  1,  0,  1,  0,  1,},
 +  {   1,  0,  1,  0,  1,  0,  1,  0,},
 +},{
 +  {   1,  2,  1,  2,  1,  2,  1,  2,},
 +  {   3,  0,  3,  0,  3,  0,  3,  0,},
 +  {   1,  2,  1,  2,  1,  2,  1,  2,},
 +  {   3,  0,  3,  0,  3,  0,  3,  0,},
 +  {   1,  2,  1,  2,  1,  2,  1,  2,},
 +  {   3,  0,  3,  0,  3,  0,  3,  0,},
 +  {   1,  2,  1,  2,  1,  2,  1,  2,},
 +  {   3,  0,  3,  0,  3,  0,  3,  0,},
 +},{
 +  {   2,  4,  3,  5,  2,  4,  3,  5,},
 +  {   6,  0,  7,  1,  6,  0,  7,  1,},
 +  {   3,  5,  2,  4,  3,  5,  2,  4,},
 +  {   7,  1,  6,  0,  7,  1,  6,  0,},
 +  {   2,  4,  3,  5,  2,  4,  3,  5,},
 +  {   6,  0,  7,  1,  6,  0,  7,  1,},
 +  {   3,  5,  2,  4,  3,  5,  2,  4,},
 +  {   7,  1,  6,  0,  7,  1,  6,  0,},
 +},{
 +  {   4,  8,  7, 11,  4,  8,  7, 11,},
 +  {  12,  0, 15,  3, 12,  0, 15,  3,},
 +  {   6, 10,  5,  9,  6, 10,  5,  9,},
 +  {  14,  2, 13,  1, 14,  2, 13,  1,},
 +  {   4,  8,  7, 11,  4,  8,  7, 11,},
 +  {  12,  0, 15,  3, 12,  0, 15,  3,},
 +  {   6, 10,  5,  9,  6, 10,  5,  9,},
 +  {  14,  2, 13,  1, 14,  2, 13,  1,},
 +},{
 +  {   9, 17, 15, 23,  8, 16, 14, 22,},
 +  {  25,  1, 31,  7, 24,  0, 30,  6,},
 +  {  13, 21, 11, 19, 12, 20, 10, 18,},
 +  {  29,  5, 27,  3, 28,  4, 26,  2,},
 +  {   8, 16, 14, 22,  9, 17, 15, 23,},
 +  {  24,  0, 30,  6, 25,  1, 31,  7,},
 +  {  12, 20, 10, 18, 13, 21, 11, 19,},
 +  {  28,  4, 26,  2, 29,  5, 27,  3,},
 +},{
 +  {  18, 34, 30, 46, 17, 33, 29, 45,},
 +  {  50,  2, 62, 14, 49,  1, 61, 13,},
 +  {  26, 42, 22, 38, 25, 41, 21, 37,},
 +  {  58, 10, 54,  6, 57,  9, 53,  5,},
 +  {  16, 32, 28, 44, 19, 35, 31, 47,},
 +  {  48,  0, 60, 12, 51,  3, 63, 15,},
 +  {  24, 40, 20, 36, 27, 43, 23, 39,},
 +  {  56,  8, 52,  4, 59, 11, 55,  7,},
 +},{
 +  {  18, 34, 30, 46, 17, 33, 29, 45,},
 +  {  50,  2, 62, 14, 49,  1, 61, 13,},
 +  {  26, 42, 22, 38, 25, 41, 21, 37,},
 +  {  58, 10, 54,  6, 57,  9, 53,  5,},
 +  {  16, 32, 28, 44, 19, 35, 31, 47,},
 +  {  48,  0, 60, 12, 51,  3, 63, 15,},
 +  {  24, 40, 20, 36, 27, 43, 23, 39,},
 +  {  56,  8, 52,  4, 59, 11, 55,  7,},
 +},{
 +  {  36, 68, 60, 92, 34, 66, 58, 90,},
 +  { 100,  4,124, 28, 98,  2,122, 26,},
 +  {  52, 84, 44, 76, 50, 82, 42, 74,},
 +  { 116, 20,108, 12,114, 18,106, 10,},
 +  {  32, 64, 56, 88, 38, 70, 62, 94,},
 +  {  96,  0,120, 24,102,  6,126, 30,},
 +  {  48, 80, 40, 72, 54, 86, 46, 78,},
 +  { 112, 16,104,  8,118, 22,110, 14,},
 +}};
 +
 +static const uint8_t flat64[8]={64,64,64,64,64,64,64,64};
 +
 +const uint16_t dither_scale[15][16]={
 +{    2,    3,    3,    5,    5,    5,    5,    5,    5,    5,    5,    5,    5,    5,    5,    5,},
 +{    2,    3,    7,    7,   13,   13,   25,   25,   25,   25,   25,   25,   25,   25,   25,   25,},
 +{    3,    3,    4,   15,   15,   29,   57,   57,   57,  113,  113,  113,  113,  113,  113,  113,},
 +{    3,    4,    4,    5,   31,   31,   61,  121,  241,  241,  241,  241,  481,  481,  481,  481,},
 +{    3,    4,    5,    5,    6,   63,   63,  125,  249,  497,  993,  993,  993,  993,  993, 1985,},
 +{    3,    5,    6,    6,    6,    7,  127,  127,  253,  505, 1009, 2017, 4033, 4033, 4033, 4033,},
 +{    3,    5,    6,    7,    7,    7,    8,  255,  255,  509, 1017, 2033, 4065, 8129,16257,16257,},
 +{    3,    5,    6,    8,    8,    8,    8,    9,  511,  511, 1021, 2041, 4081, 8161,16321,32641,},
 +{    3,    5,    7,    8,    9,    9,    9,    9,   10, 1023, 1023, 2045, 4089, 8177,16353,32705,},
 +{    3,    5,    7,    8,   10,   10,   10,   10,   10,   11, 2047, 2047, 4093, 8185,16369,32737,},
 +{    3,    5,    7,    8,   10,   11,   11,   11,   11,   11,   12, 4095, 4095, 8189,16377,32753,},
 +{    3,    5,    7,    9,   10,   12,   12,   12,   12,   12,   12,   13, 8191, 8191,16381,32761,},
 +{    3,    5,    7,    9,   10,   12,   13,   13,   13,   13,   13,   13,   14,16383,16383,32765,},
 +{    3,    5,    7,    9,   10,   12,   14,   14,   14,   14,   14,   14,   14,   15,32767,32767,},
 +{    3,    5,    7,    9,   11,   12,   14,   15,   15,   15,   15,   15,   15,   15,   16,65535,},
 +};
 +
  #define output_pixel(pos, val, bias, signedness) \
      if (big_endian) { \
          AV_WB16(pos, bias + av_clip_ ## signedness ## 16(val >> shift)); \
@@@ -302,8 -207,7 +302,8 @@@ yuv2plane1_16_c_template(const int32_t 
                           int big_endian, int output_bits)
  {
      int i;
 -    int shift = 19 - output_bits;
 +    int shift = 3;
 +    av_assert0(output_bits == 16);
  
      for (i = 0; i < dstW; i++) {
          int val = src[i] + (1 << (shift - 1));
@@@ -317,11 -221,10 +317,11 @@@ yuv2planeX_16_c_template(const int16_t 
                           int big_endian, int output_bits)
  {
      int i;
 -    int shift = 15 + 16 - output_bits;
 +    int shift = 15;
 +    av_assert0(output_bits == 16);
  
      for (i = 0; i < dstW; i++) {
 -        int val = 1 << (30-output_bits);
 +        int val = 1 << (shift - 1);
          int j;
  
          /* range of val is [0,0x7FFFFFFF], so 31 bits, but with lanczos/spline
@@@ -368,7 -271,7 +368,7 @@@ yuv2planeX_10_c_template(const int16_t 
      int shift = 11 + 16 - output_bits;
  
      for (i = 0; i < dstW; i++) {
 -        int val = 1 << (26-output_bits);
 +        int val = 1 << (shift - 1);
          int j;
  
          for (j = 0; j < filterSize; j++)
@@@ -530,8 -433,8 +530,8 @@@ yuv2gray16_1_c_template(SwsContext *c, 
      int i;
  
      for (i = 0; i < (dstW >> 1); i++) {
 -        int Y1 = buf0[i * 2    ] << 1;
 -        int Y2 = buf0[i * 2 + 1] << 1;
 +        int Y1 = (buf0[i * 2    ]+4)>>3;
 +        int Y2 = (buf0[i * 2 + 1]+4)>>3;
  
          output_pixel(&dest[i * 2 + 0], Y1);
          output_pixel(&dest[i * 2 + 1], Y2);
@@@ -979,8 -882,8 +979,8 @@@ yuv2rgb48_1_c_template(SwsContext *c, c
          for (i = 0; i < (dstW >> 1); i++) {
              int Y1 = (buf0[i * 2]    ) >> 2;
              int Y2 = (buf0[i * 2 + 1]) >> 2;
 -            int U  = (ubuf0[i] + ubuf1[i] + (-128 << 11)) >> 3;
 -            int V  = (vbuf0[i] + vbuf1[i] + (-128 << 11)) >> 3;
 +            int U  = (ubuf0[i] + ubuf1[i] + (-128 << 12)) >> 3;
 +            int V  = (vbuf0[i] + vbuf1[i] + (-128 << 12)) >> 3;
              int R, G, B;
  
              Y1 -= c->yuv2rgb_y_offset;
@@@ -1051,7 -954,6 +1051,7 @@@ yuv2rgb_write(uint8_t *_dest, int i, in
  
  #define r_b ((target == PIX_FMT_RGB24) ? r : b)
  #define b_r ((target == PIX_FMT_RGB24) ? b : r)
 +
          dest[i * 6 + 0] = r_b[Y1];
          dest[i * 6 + 1] =   g[Y1];
          dest[i * 6 + 2] = b_r[Y1];
@@@ -1342,9 -1244,9 +1342,9 @@@ yuv2rgb_full_X_c_template(SwsContext *c
  
      for (i = 0; i < dstW; i++) {
          int j;
 -        int Y = 0;
 -        int U = -128 << 19;
 -        int V = -128 << 19;
 +        int Y = 1<<9;
 +        int U = (1<<9)-(128 << 19);
 +        int V = (1<<9)-(128 << 19);
          int av_unused A;
          int R, G, B;
  
          U >>= 10;
          V >>= 10;
          if (hasAlpha) {
 -            A = 1 << 21;
 +            A = 1 << 18;
              for (j = 0; j < lumFilterSize; j++) {
                  A += alpSrc[j][i] * lumFilter[j];
              }
              dest[1] = B >> 22;
              dest[2] = G >> 22;
              dest[3] = R >> 22;
 -            dest += 4;
              break;
          case PIX_FMT_BGR24:
              dest[0] = B >> 22;
@@@ -1509,7 -1412,7 +1509,7 @@@ rgb48ToUV_half_c_template(uint16_t *dst
  #undef input_pixel
  
  #define rgb48funcs(pattern, BE_LE, origin) \
 -static void pattern ## 48 ## BE_LE ## ToY_c(uint8_t *_dst, const uint8_t *_src, \
 +static void pattern ## 48 ## BE_LE ## ToY_c(uint8_t *_dst, const uint8_t *_src, const uint8_t *unused0, const uint8_t *unused1,\
                                      int width, uint32_t *unused) \
  { \
      const uint16_t *src = (const uint16_t *) _src; \
  } \
   \
  static void pattern ## 48 ## BE_LE ## ToUV_c(uint8_t *_dstU, uint8_t *_dstV, \
 -                                    const uint8_t *_src1, const uint8_t *_src2, \
 +                                    const uint8_t *unused0, const uint8_t *_src1, const uint8_t *_src2, \
                                      int width, uint32_t *unused) \
  { \
      const uint16_t *src1 = (const uint16_t *) _src1, \
  } \
   \
  static void pattern ## 48 ## BE_LE ## ToUV_half_c(uint8_t *_dstU, uint8_t *_dstV, \
 -                                    const uint8_t *_src1, const uint8_t *_src2, \
 +                                    const uint8_t *unused0, const uint8_t *_src1, const uint8_t *_src2, \
                                      int width, uint32_t *unused) \
  { \
      const uint16_t *src1 = (const uint16_t *) _src1, \
@@@ -1547,14 -1450,14 +1547,14 @@@ rgb48funcs(bgr, BE, PIX_FMT_BGR48BE)
                          (isBE(origin) ? AV_RB16(&src[(i)*2]) : AV_RL16(&src[(i)*2])))
  
  static av_always_inline void
 -rgb16_32ToY_c_template(uint8_t *dst, const uint8_t *src,
 +rgb16_32ToY_c_template(int16_t *dst, const uint8_t *src,
                         int width, enum PixelFormat origin,
                         int shr,   int shg,   int shb, int shp,
                         int maskr, int maskg, int maskb,
                         int rsh,   int gsh,   int bsh, int S)
  {
      const int ry = RY << rsh, gy = GY << gsh, by = BY << bsh,
 -              rnd = 33 << (S - 1);
 +              rnd = (32<<((S)-1)) + (1<<(S-7));
      int i;
  
      for (i = 0; i < width; i++) {
          int g = (px & maskg) >> shg;
          int r = (px & maskr) >> shr;
  
 -        dst[i] = (ry * r + gy * g + by * b + rnd) >> S;
 +        dst[i] = (ry * r + gy * g + by * b + rnd) >> ((S)-6);
      }
  }
  
  static av_always_inline void
 -rgb16_32ToUV_c_template(uint8_t *dstU, uint8_t *dstV,
 +rgb16_32ToUV_c_template(int16_t *dstU, int16_t *dstV,
                          const uint8_t *src, int width,
                          enum PixelFormat origin,
                          int shr,   int shg,   int shb, int shp,
  {
      const int ru = RU << rsh, gu = GU << gsh, bu = BU << bsh,
                rv = RV << rsh, gv = GV << gsh, bv = BV << bsh,
 -              rnd = 257 << (S - 1);
 +              rnd = (256<<((S)-1)) + (1<<(S-7));
      int i;
  
      for (i = 0; i < width; i++) {
          int g = (px & maskg) >> shg;
          int r = (px & maskr) >> shr;
  
 -        dstU[i] = (ru * r + gu * g + bu * b + rnd) >> S;
 -        dstV[i] = (rv * r + gv * g + bv * b + rnd) >> S;
 +        dstU[i] = (ru * r + gu * g + bu * b + rnd) >> ((S)-6);
 +        dstV[i] = (rv * r + gv * g + bv * b + rnd) >> ((S)-6);
      }
  }
  
  static av_always_inline void
 -rgb16_32ToUV_half_c_template(uint8_t *dstU, uint8_t *dstV,
 +rgb16_32ToUV_half_c_template(int16_t *dstU, int16_t *dstV,
                               const uint8_t *src, int width,
                               enum PixelFormat origin,
                               int shr,   int shg,   int shb, int shp,
  {
      const int ru = RU << rsh, gu = GU << gsh, bu = BU << bsh,
                rv = RV << rsh, gv = GV << gsh, bv = BV << bsh,
 -              rnd = 257 << S, maskgx = ~(maskr | maskb);
 +              rnd = (256U<<(S)) + (1<<(S-6)), maskgx = ~(maskr | maskb);
      int i;
  
      maskr |= maskr << 1; maskb |= maskb << 1; maskg |= maskg << 1;
          }
          r = (rb & maskr) >> shr;
  
 -        dstU[i] = (ru * r + gu * g + bu * b + rnd) >> (S + 1);
 -        dstV[i] = (rv * r + gv * g + bv * b + rnd) >> (S + 1);
 +        dstU[i] = (ru * r + gu * g + bu * b + (unsigned)rnd) >> ((S)-6+1);
 +        dstV[i] = (rv * r + gv * g + bv * b + (unsigned)rnd) >> ((S)-6+1);
      }
  }
  
  
  #define rgb16_32_wrapper(fmt, name, shr, shg, shb, shp, maskr, \
                           maskg, maskb, rsh, gsh, bsh, S) \
 -static void name ## ToY_c(uint8_t *dst, const uint8_t *src, \
 +static void name ## ToY_c(uint8_t *dst, const uint8_t *src, const uint8_t *unused1, const uint8_t *unused2, \
                            int width, uint32_t *unused) \
  { \
 -    rgb16_32ToY_c_template(dst, src, width, fmt, shr, shg, shb, shp, \
 +    rgb16_32ToY_c_template((int16_t*)dst, src, width, fmt, \
 +                           shr, shg, shb, shp, \
                             maskr, maskg, maskb, rsh, gsh, bsh, S); \
  } \
   \
  static void name ## ToUV_c(uint8_t *dstU, uint8_t *dstV, \
 -                           const uint8_t *src, const uint8_t *dummy, \
 +                           const uint8_t *unused0, const uint8_t *src, const uint8_t *dummy, \
                             int width, uint32_t *unused) \
  { \
 -    rgb16_32ToUV_c_template(dstU, dstV, src, width, fmt, shr, shg, shb, shp, \
 +    rgb16_32ToUV_c_template((int16_t*)dstU, (int16_t*)dstV, src, width, fmt,  \
 +                            shr, shg, shb, shp, \
                              maskr, maskg, maskb, rsh, gsh, bsh, S); \
  } \
   \
  static void name ## ToUV_half_c(uint8_t *dstU, uint8_t *dstV, \
 -                                const uint8_t *src, const uint8_t *dummy, \
 +                                const uint8_t *unused0, const uint8_t *src, const uint8_t *dummy, \
                                  int width, uint32_t *unused) \
  { \
 -    rgb16_32ToUV_half_c_template(dstU, dstV, src, width, fmt, shr, shg, shb, shp, \
 +    rgb16_32ToUV_half_c_template((int16_t*)dstU, (int16_t*)dstV, src, width, fmt, \
 +                                 shr, shg, shb, shp, \
                                   maskr, maskg, maskb, rsh, gsh, bsh, S); \
  }
  
@@@ -1668,132 -1568,71 +1668,132 @@@ rgb16_32_wrapper(PIX_FMT_BGR555BE, bgr1
  rgb16_32_wrapper(PIX_FMT_RGB565BE, rgb16be, 0, 0,  0, 0,   0xF800, 0x07E0,   0x001F,  0, 5, 11, RGB2YUV_SHIFT+8);
  rgb16_32_wrapper(PIX_FMT_RGB555BE, rgb15be, 0, 0,  0, 0,   0x7C00, 0x03E0,   0x001F,  0, 5, 10, RGB2YUV_SHIFT+7);
  
 -static void abgrToA_c(uint8_t *dst, const uint8_t *src, int width, uint32_t *unused)
 +static void gbr24pToY_c(uint16_t *dst, const uint8_t *gsrc, const uint8_t *bsrc, const uint8_t *rsrc,
 +                        int width, uint32_t *unused)
 +{
 +    int i;
 +    for (i = 0; i < width; i++) {
 +        unsigned int g   = gsrc[i];
 +        unsigned int b   = bsrc[i];
 +        unsigned int r   = rsrc[i];
 +
 +        dst[i] = (RY*r + GY*g + BY*b + (0x801<<(RGB2YUV_SHIFT-7))) >> (RGB2YUV_SHIFT-6);
 +    }
 +}
 +
 +static void gbr24pToUV_c(uint16_t *dstU, uint16_t *dstV,
 +                         const uint8_t *gsrc, const uint8_t *bsrc, const uint8_t *rsrc,
 +                         int width, enum PixelFormat origin)
 +{
 +    int i;
 +    for (i = 0; i < width; i++) {
 +        unsigned int g   = gsrc[i];
 +        unsigned int b   = bsrc[i];
 +        unsigned int r   = rsrc[i];
 +
 +        dstU[i] = (RU*r + GU*g + BU*b + (0x4001<<(RGB2YUV_SHIFT-7))) >> (RGB2YUV_SHIFT-6);
 +        dstV[i] = (RV*r + GV*g + BV*b + (0x4001<<(RGB2YUV_SHIFT-7))) >> (RGB2YUV_SHIFT-6);
 +    }
 +}
 +
 +static void gbr24pToUV_half_c(uint16_t *dstU, uint16_t *dstV,
 +                         const uint8_t *gsrc, const uint8_t *bsrc, const uint8_t *rsrc,
 +                         int width, enum PixelFormat origin)
 +{
 +    int i;
 +    for (i = 0; i < width; i++) {
 +        unsigned int g   = gsrc[2*i] + gsrc[2*i+1];
 +        unsigned int b   = bsrc[2*i] + bsrc[2*i+1];
 +        unsigned int r   = rsrc[2*i] + rsrc[2*i+1];
 +
 +        dstU[i] = (RU*r + GU*g + BU*b + (0x4001<<(RGB2YUV_SHIFT-6))) >> (RGB2YUV_SHIFT-6+1);
 +        dstV[i] = (RV*r + GV*g + BV*b + (0x4001<<(RGB2YUV_SHIFT-6))) >> (RGB2YUV_SHIFT-6+1);
 +    }
 +}
 +
 +static void abgrToA_c(int16_t *dst, const uint8_t *src, const uint8_t *unused1, const uint8_t *unused2, int width, uint32_t *unused)
  {
      int i;
      for (i=0; i<width; i++) {
 -        dst[i]= src[4*i];
 +        dst[i]= src[4*i]<<6;
      }
  }
  
 -static void rgbaToA_c(uint8_t *dst, const uint8_t *src, int width, uint32_t *unused)
 +static void rgbaToA_c(int16_t *dst, const uint8_t *src, const uint8_t *unused1, const uint8_t *unused2, int width, uint32_t *unused)
  {
      int i;
      for (i=0; i<width; i++) {
 -        dst[i]= src[4*i+3];
 +        dst[i]= src[4*i+3]<<6;
      }
  }
  
 -static void palToY_c(uint8_t *dst, const uint8_t *src, int width, uint32_t *pal)
 +static void palToA_c(int16_t *dst, const uint8_t *src, const uint8_t *unused1, const uint8_t *unused2, int width, uint32_t *pal)
  {
      int i;
      for (i=0; i<width; i++) {
          int d= src[i];
  
 -        dst[i]= pal[d] & 0xFF;
 +        dst[i]= (pal[d] >> 24)<<6;
      }
  }
  
 -static void palToUV_c(uint8_t *dstU, uint8_t *dstV,
 -                      const uint8_t *src1, const uint8_t *src2,
 -                      int width, uint32_t *pal)
 +static void palToY_c(int16_t *dst, const uint8_t *src, const uint8_t *unused1, const uint8_t *unused2, long width, uint32_t *pal)
 +{
 +    int i;
 +    for (i=0; i<width; i++) {
 +        int d= src[i];
 +
 +        dst[i]= (pal[d] & 0xFF)<<6;
 +    }
 +}
 +
 +static void palToUV_c(uint16_t *dstU, int16_t *dstV,
 +                           const uint8_t *unused0, const uint8_t *src1, const uint8_t *src2,
 +                           int width, uint32_t *pal)
  {
      int i;
      assert(src1 == src2);
      for (i=0; i<width; i++) {
          int p= pal[src1[i]];
  
 -        dstU[i]= p>>8;
 -        dstV[i]= p>>16;
 +        dstU[i]= (uint8_t)(p>> 8)<<6;
 +        dstV[i]= (uint8_t)(p>>16)<<6;
      }
  }
  
 -static void monowhite2Y_c(uint8_t *dst, const uint8_t *src,
 -                          int width, uint32_t *unused)
 +static void monowhite2Y_c(int16_t *dst, const uint8_t *src, const uint8_t *unused1, const uint8_t *unused2,  int width, uint32_t *unused)
  {
      int i, j;
      for (i=0; i<width/8; i++) {
          int d= ~src[i];
          for(j=0; j<8; j++)
 -            dst[8*i+j]= ((d>>(7-j))&1)*255;
 +            dst[8*i+j]= ((d>>(7-j))&1)*16383;
 +    }
 +    if(width&7){
 +        int d= ~src[i];
 +        for(j=0; j<(width&7); j++)
 +            dst[8*i+j]= ((d>>(7-j))&1)*16383;
      }
  }
  
 -static void monoblack2Y_c(uint8_t *dst, const uint8_t *src,
 -                          int width, uint32_t *unused)
 +static void monoblack2Y_c(int16_t *dst, const uint8_t *src, const uint8_t *unused1, const uint8_t *unused2,  int width, uint32_t *unused)
  {
      int i, j;
      for (i=0; i<width/8; i++) {
          int d= src[i];
          for(j=0; j<8; j++)
 -            dst[8*i+j]= ((d>>(7-j))&1)*255;
 +            dst[8*i+j]= ((d>>(7-j))&1)*16383;
 +    }
 +    if(width&7){
 +        int d= src[i];
 +        for(j=0; j<(width&7); j++)
 +            dst[8*i+j]= ((d>>(7-j))&1)*16383;
      }
  }
  
  //FIXME yuy2* can read up to 7 samples too much
  
 -static void yuy2ToY_c(uint8_t *dst, const uint8_t *src, int width,
 +static void yuy2ToY_c(uint8_t *dst, const uint8_t *src, const uint8_t *unused1, const uint8_t *unused2,  int width,
                        uint32_t *unused)
  {
      int i;
          dst[i]= src[2*i];
  }
  
 -static void yuy2ToUV_c(uint8_t *dstU, uint8_t *dstV, const uint8_t *src1,
 +static void yuy2ToUV_c(uint8_t *dstU, uint8_t *dstV, const uint8_t *unused0, const uint8_t *src1,
                         const uint8_t *src2, int width, uint32_t *unused)
  {
      int i;
      assert(src1 == src2);
  }
  
 -static void bswap16Y_c(uint8_t *_dst, const uint8_t *_src, int width, uint32_t *unused)
 +static void bswap16Y_c(uint8_t *_dst, const uint8_t *_src, const uint8_t *unused1, const uint8_t *unused2,  int width, uint32_t *unused)
  {
      int i;
      const uint16_t *src = (const uint16_t *) _src;
      }
  }
  
 -static void bswap16UV_c(uint8_t *_dstU, uint8_t *_dstV, const uint8_t *_src1,
 +static void bswap16UV_c(uint8_t *_dstU, uint8_t *_dstV, const uint8_t *unused0, const uint8_t *_src1,
                          const uint8_t *_src2, int width, uint32_t *unused)
  {
      int i;
  
  /* This is almost identical to the previous, end exists only because
   * yuy2ToY/UV)(dst, src+1, ...) would have 100% unaligned accesses. */
 -static void uyvyToY_c(uint8_t *dst, const uint8_t *src, int width,
 +static void uyvyToY_c(uint8_t *dst, const uint8_t *src, const uint8_t *unused1, const uint8_t *unused2,  int width,
                        uint32_t *unused)
  {
      int i;
          dst[i]= src[2*i+1];
  }
  
 -static void uyvyToUV_c(uint8_t *dstU, uint8_t *dstV, const uint8_t *src1,
 +static void uyvyToUV_c(uint8_t *dstU, uint8_t *dstV, const uint8_t *unused0, const uint8_t *src1,
                         const uint8_t *src2, int width, uint32_t *unused)
  {
      int i;
@@@ -1867,14 -1706,14 +1867,14 @@@ static av_always_inline void nvXXtoUV_c
  }
  
  static void nv12ToUV_c(uint8_t *dstU, uint8_t *dstV,
 -                       const uint8_t *src1, const uint8_t *src2,
 +                       const uint8_t *unused0, const uint8_t *src1, const uint8_t *src2,
                         int width, uint32_t *unused)
  {
      nvXXtoUV_c(dstU, dstV, src1, width);
  }
  
  static void nv21ToUV_c(uint8_t *dstU, uint8_t *dstV,
 -                       const uint8_t *src1, const uint8_t *src2,
 +                       const uint8_t *unused0, const uint8_t *src1, const uint8_t *src2,
                         int width, uint32_t *unused)
  {
      nvXXtoUV_c(dstV, dstU, src1, width);
  
  #define input_pixel(pos) (isBE(origin) ? AV_RB16(pos) : AV_RL16(pos))
  
 -static void bgr24ToY_c(uint8_t *dst, const uint8_t *src,
 +static void bgr24ToY_c(int16_t *dst, const uint8_t *src, const uint8_t *unused1, const uint8_t *unused2,
                         int width, uint32_t *unused)
  {
      int i;
          int g= src[i*3+1];
          int r= src[i*3+2];
  
 -        dst[i]= ((RY*r + GY*g + BY*b + (33<<(RGB2YUV_SHIFT-1)))>>RGB2YUV_SHIFT);
 +        dst[i]= ((RY*r + GY*g + BY*b + (32<<(RGB2YUV_SHIFT-1)) + (1<<(RGB2YUV_SHIFT-7)))>>(RGB2YUV_SHIFT-6));
      }
  }
  
 -static void bgr24ToUV_c(uint8_t *dstU, uint8_t *dstV, const uint8_t *src1,
 +static void bgr24ToUV_c(int16_t *dstU, int16_t *dstV, const uint8_t *unused0, const uint8_t *src1,
                          const uint8_t *src2, int width, uint32_t *unused)
  {
      int i;
          int g= src1[3*i + 1];
          int r= src1[3*i + 2];
  
 -        dstU[i]= (RU*r + GU*g + BU*b + (257<<(RGB2YUV_SHIFT-1)))>>RGB2YUV_SHIFT;
 -        dstV[i]= (RV*r + GV*g + BV*b + (257<<(RGB2YUV_SHIFT-1)))>>RGB2YUV_SHIFT;
 +        dstU[i]= (RU*r + GU*g + BU*b + (256<<(RGB2YUV_SHIFT-1)) + (1<<(RGB2YUV_SHIFT-7)))>>(RGB2YUV_SHIFT-6);
 +        dstV[i]= (RV*r + GV*g + BV*b + (256<<(RGB2YUV_SHIFT-1)) + (1<<(RGB2YUV_SHIFT-7)))>>(RGB2YUV_SHIFT-6);
      }
      assert(src1 == src2);
  }
  
 -static void bgr24ToUV_half_c(uint8_t *dstU, uint8_t *dstV, const uint8_t *src1,
 +static void bgr24ToUV_half_c(int16_t *dstU, int16_t *dstV, const uint8_t *unused0, const uint8_t *src1,
                               const uint8_t *src2, int width, uint32_t *unused)
  {
      int i;
          int g= src1[6*i + 1] + src1[6*i + 4];
          int r= src1[6*i + 2] + src1[6*i + 5];
  
 -        dstU[i]= (RU*r + GU*g + BU*b + (257<<RGB2YUV_SHIFT))>>(RGB2YUV_SHIFT+1);
 -        dstV[i]= (RV*r + GV*g + BV*b + (257<<RGB2YUV_SHIFT))>>(RGB2YUV_SHIFT+1);
 +        dstU[i]= (RU*r + GU*g + BU*b + (256<<RGB2YUV_SHIFT) + (1<<(RGB2YUV_SHIFT-6)))>>(RGB2YUV_SHIFT-5);
 +        dstV[i]= (RV*r + GV*g + BV*b + (256<<RGB2YUV_SHIFT) + (1<<(RGB2YUV_SHIFT-6)))>>(RGB2YUV_SHIFT-5);
      }
      assert(src1 == src2);
  }
  
 -static void rgb24ToY_c(uint8_t *dst, const uint8_t *src, int width,
 +static void rgb24ToY_c(int16_t *dst, const uint8_t *src, const uint8_t *unused1, const uint8_t *unused2, int width,
                         uint32_t *unused)
  {
      int i;
          int g= src[i*3+1];
          int b= src[i*3+2];
  
 -        dst[i]= ((RY*r + GY*g + BY*b + (33<<(RGB2YUV_SHIFT-1)))>>RGB2YUV_SHIFT);
 +        dst[i]= ((RY*r + GY*g + BY*b + (32<<(RGB2YUV_SHIFT-1)) + (1<<(RGB2YUV_SHIFT-7)))>>(RGB2YUV_SHIFT-6));
      }
  }
  
 -static void rgb24ToUV_c(uint8_t *dstU, uint8_t *dstV, const uint8_t *src1,
 +static void rgb24ToUV_c(int16_t *dstU, int16_t *dstV, const uint8_t *unused0, const uint8_t *src1,
                          const uint8_t *src2, int width, uint32_t *unused)
  {
      int i;
          int g= src1[3*i + 1];
          int b= src1[3*i + 2];
  
 -        dstU[i]= (RU*r + GU*g + BU*b + (257<<(RGB2YUV_SHIFT-1)))>>RGB2YUV_SHIFT;
 -        dstV[i]= (RV*r + GV*g + BV*b + (257<<(RGB2YUV_SHIFT-1)))>>RGB2YUV_SHIFT;
 +        dstU[i]= (RU*r + GU*g + BU*b + (256<<(RGB2YUV_SHIFT-1)) + (1<<(RGB2YUV_SHIFT-7)))>>(RGB2YUV_SHIFT-6);
 +        dstV[i]= (RV*r + GV*g + BV*b + (256<<(RGB2YUV_SHIFT-1)) + (1<<(RGB2YUV_SHIFT-7)))>>(RGB2YUV_SHIFT-6);
      }
  }
  
 -static void rgb24ToUV_half_c(uint8_t *dstU, uint8_t *dstV, const uint8_t *src1,
 -                             const uint8_t *src2, int width, uint32_t *unused)
 +static void rgb24ToUV_half_c(int16_t *dstU, int16_t *dstV, const uint8_t *unused0, const uint8_t *src1,
 +                                    const uint8_t *src2, int width, uint32_t *unused)
  {
      int i;
      assert(src1==src2);
          int g= src1[6*i + 1] + src1[6*i + 4];
          int b= src1[6*i + 2] + src1[6*i + 5];
  
 -        dstU[i]= (RU*r + GU*g + BU*b + (257<<RGB2YUV_SHIFT))>>(RGB2YUV_SHIFT+1);
 -        dstV[i]= (RV*r + GV*g + BV*b + (257<<RGB2YUV_SHIFT))>>(RGB2YUV_SHIFT+1);
 +        dstU[i]= (RU*r + GU*g + BU*b + (256<<RGB2YUV_SHIFT) + (1<<(RGB2YUV_SHIFT-6)))>>(RGB2YUV_SHIFT-5);
 +        dstV[i]= (RV*r + GV*g + BV*b + (256<<RGB2YUV_SHIFT) + (1<<(RGB2YUV_SHIFT-6)))>>(RGB2YUV_SHIFT-5);
      }
  }
  
 -static void planar_rgb_to_y(uint8_t *dst, const uint8_t *src[4], int width)
++static void planar_rgb_to_y(uint16_t *dst, const uint8_t *src[4], int width)
+ {
+     int i;
+     for (i = 0; i < width; i++) {
+         int g = src[0][i];
+         int b = src[1][i];
+         int r = src[2][i];
 -        dst[i] = ((RY * r + GY * g + BY * b + (33 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT);
++        dst[i] = (RY*r + GY*g + BY*b + (0x801<<(RGB2YUV_SHIFT-7))) >> (RGB2YUV_SHIFT-6);
+     }
+ }
+ static void planar_rgb16le_to_y(uint8_t *_dst, const uint8_t *_src[4], int width)
+ {
+     int i;
+     const uint16_t **src = (const uint16_t **) _src;
+     uint16_t *dst = (uint16_t *) _dst;
+     for (i = 0; i < width; i++) {
+         int g = AV_RL16(src[0] + i);
+         int b = AV_RL16(src[1] + i);
+         int r = AV_RL16(src[2] + i);
+         dst[i] = ((RY * r + GY * g + BY * b + (33 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT);
+     }
+ }
+ static void planar_rgb16be_to_y(uint8_t *_dst, const uint8_t *_src[4], int width)
+ {
+     int i;
+     const uint16_t **src = (const uint16_t **) _src;
+     uint16_t *dst = (uint16_t *) _dst;
+     for (i = 0; i < width; i++) {
+         int g = AV_RB16(src[0] + i);
+         int b = AV_RB16(src[1] + i);
+         int r = AV_RB16(src[2] + i);
+         dst[i] = ((RY * r + GY * g + BY * b + (33 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT);
+     }
+ }
 -static void planar_rgb_to_uv(uint8_t *dstU, uint8_t *dstV, const uint8_t *src[4], int width)
++static void planar_rgb_to_uv(uint16_t *dstU, uint16_t *dstV, const uint8_t *src[4], int width)
+ {
+     int i;
+     for (i = 0; i < width; i++) {
+         int g = src[0][i];
+         int b = src[1][i];
+         int r = src[2][i];
 -        dstU[i] = (RU * r + GU * g + BU * b + (257 << RGB2YUV_SHIFT)) >> (RGB2YUV_SHIFT + 1);
 -        dstV[i] = (RV * r + GV * g + BV * b + (257 << RGB2YUV_SHIFT)) >> (RGB2YUV_SHIFT + 1);
++        dstU[i] = (RU*r + GU*g + BU*b + (0x4001<<(RGB2YUV_SHIFT-7))) >> (RGB2YUV_SHIFT-6);
++        dstV[i] = (RV*r + GV*g + BV*b + (0x4001<<(RGB2YUV_SHIFT-7))) >> (RGB2YUV_SHIFT-6);
+     }
+ }
+ static void planar_rgb16le_to_uv(uint8_t *_dstU, uint8_t *_dstV, const uint8_t *_src[4], int width)
+ {
+     int i;
+     const uint16_t **src = (const uint16_t **) _src;
+     uint16_t *dstU = (uint16_t *) _dstU;
+     uint16_t *dstV = (uint16_t *) _dstV;
+     for (i = 0; i < width; i++) {
+         int g = AV_RL16(src[0] + i);
+         int b = AV_RL16(src[1] + i);
+         int r = AV_RL16(src[2] + i);
+         dstU[i] = (RU * r + GU * g + BU * b + (257 << RGB2YUV_SHIFT)) >> (RGB2YUV_SHIFT + 1);
+         dstV[i] = (RV * r + GV * g + BV * b + (257 << RGB2YUV_SHIFT)) >> (RGB2YUV_SHIFT + 1);
+     }
+ }
+ static void planar_rgb16be_to_uv(uint8_t *_dstU, uint8_t *_dstV, const uint8_t *_src[4], int width)
+ {
+     int i;
+     const uint16_t **src = (const uint16_t **) _src;
+     uint16_t *dstU = (uint16_t *) _dstU;
+     uint16_t *dstV = (uint16_t *) _dstV;
+     for (i = 0; i < width; i++) {
+         int g = AV_RB16(src[0] + i);
+         int b = AV_RB16(src[1] + i);
+         int r = AV_RB16(src[2] + i);
+         dstU[i] = (RU * r + GU * g + BU * b + (257 << RGB2YUV_SHIFT)) >> (RGB2YUV_SHIFT + 1);
+         dstV[i] = (RV * r + GV * g + BV * b + (257 << RGB2YUV_SHIFT)) >> (RGB2YUV_SHIFT + 1);
+     }
+ }
  static void hScale16To19_c(SwsContext *c, int16_t *_dst, int dstW, const uint8_t *_src,
                             const int16_t *filter,
                             const int16_t *filterPos, int filterSize)
      int bits = av_pix_fmt_descriptors[c->srcFormat].comp[0].depth_minus1;
      int sh = bits - 4;
  
 +    if((isAnyRGB(c->srcFormat) || c->srcFormat==PIX_FMT_PAL8) && av_pix_fmt_descriptors[c->srcFormat].comp[0].depth_minus1<15)
 +        sh= 9;
 +
      for (i = 0; i < dstW; i++) {
          int j;
          int srcPos = filterPos[i];
@@@ -2002,9 -1923,6 +2087,9 @@@ static void hScale16To15_c(SwsContext *
      const uint16_t *src = (const uint16_t *) _src;
      int sh = av_pix_fmt_descriptors[c->srcFormat].comp[0].depth_minus1;
  
 +    if(sh<15)
 +        sh= isAnyRGB(c->srcFormat) || c->srcFormat==PIX_FMT_PAL8 ? 13 : av_pix_fmt_descriptors[c->srcFormat].comp[0].depth_minus1;
 +
      for (i = 0; i < dstW; i++) {
          int j;
          int srcPos = filterPos[i];
@@@ -2119,7 -2037,7 +2204,7 @@@ static void lumRangeFromJpeg16_c(int16_
      int i;
      int32_t *dst = (int32_t *) _dst;
      for (i = 0; i < width; i++)
 -        dst[i] = (dst[i]*14071 + (33561947<<4))>>14;
 +        dst[i] = (dst[i]*(14071/4) + (33561947<<4)/4)>>12;
  }
  
  static void hyscale_fast_c(SwsContext *c, int16_t *dst, int dstWidth,
          dst[i]= (src[xx]<<7) + (src[xx+1] - src[xx])*xalpha;
          xpos+=xInc;
      }
 +    for (i=dstWidth-1; (i*xInc)>>16 >=srcW-1; i--)
 +        dst[i] = src[srcW-1]*128;
  }
  
  // *** horizontal scale Y line to temp buffer
  static av_always_inline void hyscale(SwsContext *c, int16_t *dst, int dstWidth,
-                                      const uint8_t *src, const uint8_t *src2, const uint8_t *src3,
-                                      int srcW, int xInc,
+                                      const uint8_t *src_in[4], int srcW, int xInc,
                                       const int16_t *hLumFilter,
                                       const int16_t *hLumFilterPos, int hLumFilterSize,
                                       uint8_t *formatConvBuffer,
                                       uint32_t *pal, int isAlpha)
  {
 -    void (*toYV12)(uint8_t *, const uint8_t *, int, uint32_t *) = isAlpha ? c->alpToYV12 : c->lumToYV12;
 +    void (*toYV12)(uint8_t *, const uint8_t *, const uint8_t *, const uint8_t *, int, uint32_t *) = isAlpha ? c->alpToYV12 : c->lumToYV12;
      void (*convertRange)(int16_t *, int) = isAlpha ? NULL : c->lumConvertRange;
+     const uint8_t *src = src_in[isAlpha ? 3 : 0];
  
      if (toYV12) {
-         toYV12(formatConvBuffer, src, src2, src3, srcW, pal);
 -        toYV12(formatConvBuffer, src, srcW, pal);
++        toYV12(formatConvBuffer, src, src_in[1], src_in[2], srcW, pal);
          src= formatConvBuffer;
+     } else if (c->readLumPlanar && !isAlpha) {
+         c->readLumPlanar(formatConvBuffer, src_in, srcW);
+         src = formatConvBuffer;
      }
  
      if (!c->hyscale_fast) {
@@@ -2177,21 -2096,23 +2265,27 @@@ static void hcscale_fast_c(SwsContext *
          dst2[i]=(src2[xx]*(xalpha^127)+src2[xx+1]*xalpha);
          xpos+=xInc;
      }
 +    for (i=dstWidth-1; (i*xInc)>>16 >=srcW-1; i--) {
 +        dst1[i] = src1[srcW-1]*128;
 +        dst2[i] = src2[srcW-1]*128;
 +    }
  }
  
  static av_always_inline void hcscale(SwsContext *c, int16_t *dst1, int16_t *dst2, int dstWidth,
-                                      const uint8_t *src0, const uint8_t *src1, const uint8_t *src2,
+                                      const uint8_t *src_in[4],
                                       int srcW, int xInc, const int16_t *hChrFilter,
                                       const int16_t *hChrFilterPos, int hChrFilterSize,
                                       uint8_t *formatConvBuffer, uint32_t *pal)
  {
+     const uint8_t *src1 = src_in[1], *src2 = src_in[2];
      if (c->chrToYV12) {
 -        uint8_t *buf2 = formatConvBuffer + FFALIGN(srcW * FFALIGN(c->srcBpc, 8) >> 3, 16);
 -        c->chrToYV12(formatConvBuffer, buf2, src1, src2, srcW, pal);
 +        uint8_t *buf2 = formatConvBuffer + FFALIGN(srcW*2+78, 16);
-         c->chrToYV12(formatConvBuffer, buf2, src0, src1, src2, srcW, pal);
++        c->chrToYV12(formatConvBuffer, buf2, src_in[0], src1, src2, srcW, pal);
+         src1= formatConvBuffer;
+         src2= buf2;
+     } else if (c->readChrPlanar) {
 -        uint8_t *buf2 = formatConvBuffer + FFALIGN(srcW * FFALIGN(c->srcBpc, 8) >> 3, 16);
++        uint8_t *buf2 = formatConvBuffer + FFALIGN(srcW*2+78, 16);
+         c->readChrPlanar(formatConvBuffer, buf2, src_in, srcW);
          src1= formatConvBuffer;
          src2= buf2;
      }
@@@ -2299,10 -2220,7 +2393,10 @@@ find_c_packed_planar_out_funcs(SwsConte
              *yuv2packedX = yuv2bgr24_full_X_c;
              break;
          }
 +        if(!*yuv2packedX)
 +            goto YUV_PACKED;
      } else {
 +        YUV_PACKED:
          switch (dstFormat) {
          case PIX_FMT_GRAY16BE:
              *yuv2packed1 = yuv2gray16BE_1_c;
@@@ -2473,6 -2391,8 +2567,6 @@@ static int swScale(SwsContext *c, cons
      int16_t *vChrFilterPos= c->vChrFilterPos;
      int16_t *hLumFilterPos= c->hLumFilterPos;
      int16_t *hChrFilterPos= c->hChrFilterPos;
 -    int16_t *vLumFilter= c->vLumFilter;
 -    int16_t *vChrFilter= c->vChrFilter;
      int16_t *hLumFilter= c->hLumFilter;
      int16_t *hChrFilter= c->hChrFilter;
      int32_t *lumMmxFilter= c->lumMmxFilter;
      const int chrSrcSliceH= -((-srcSliceH) >> c->chrSrcVSubSample);
      int lastDstY;
      uint32_t *pal=c->pal_yuv;
 +    int should_dither= isNBPS(c->srcFormat) || is16BPS(c->srcFormat);
 +
      yuv2planar1_fn yuv2plane1 = c->yuv2plane1;
      yuv2planarX_fn yuv2planeX = c->yuv2planeX;
      yuv2interleavedX_fn yuv2nv12cX = c->yuv2nv12cX;
      yuv2packed1_fn yuv2packed1 = c->yuv2packed1;
      yuv2packed2_fn yuv2packed2 = c->yuv2packed2;
      yuv2packedX_fn yuv2packedX = c->yuv2packedX;
 -    int should_dither = is9_OR_10BPS(c->srcFormat) || is16BPS(c->srcFormat);
  
      /* vars which will change and which we need to store back in the context */
      int dstY= c->dstY;
      DEBUG_BUFFERS("vLumFilterSize: %d vLumBufSize: %d vChrFilterSize: %d vChrBufSize: %d\n",
                     vLumFilterSize,    vLumBufSize,    vChrFilterSize,    vChrBufSize);
  
 -    if (dstStride[0]%8 !=0 || dstStride[1]%8 !=0 || dstStride[2]%8 !=0 || dstStride[3]%8 != 0) {
 +    if (dstStride[0]%16 !=0 || dstStride[1]%16 !=0 || dstStride[2]%16 !=0 || dstStride[3]%16 != 0) {
          static int warnedAlready=0; //FIXME move this into the context perhaps
          if (flags & SWS_PRINT_INFO && !warnedAlready) {
              av_log(c, AV_LOG_WARNING, "Warning: dstStride is not aligned!\n"
          }
      }
  
 +    if ((int)dst[0]%16 || (int)dst[1]%16 || (int)dst[2]%16 || (int)src[0]%16 || (int)src[1]%16 || (int)src[2]%16
 +        || dstStride[0]%16 || dstStride[1]%16 || dstStride[2]%16 || dstStride[3]%16
 +        || srcStride[0]%16 || srcStride[1]%16 || srcStride[2]%16 || srcStride[3]%16
 +    ) {
 +        static int warnedAlready=0;
 +        int cpu_flags = av_get_cpu_flags();
 +        if (HAVE_MMX2 && (cpu_flags & AV_CPU_FLAG_SSE2) && !warnedAlready){
 +            av_log(c, AV_LOG_WARNING, "Warning: data is not aligned! This can lead to a speedloss\n");
 +            warnedAlready=1;
 +        }
 +    }
 +
      /* Note the user might start scaling the picture in the middle so this
         will not get executed. This is not really intended but works
         currently, so people might do it. */
              dst[2] + dstStride[2] * chrDstY,
              (CONFIG_SWSCALE_ALPHA && alpPixBuf) ? dst[3] + dstStride[3] * dstY : NULL,
          };
 +        int use_mmx_vfilter= c->use_mmx_vfilter;
  
          const int firstLumSrcY= vLumFilterPos[dstY]; //First line needed as input
          const int firstLumSrcY2= vLumFilterPos[FFMIN(dstY | ((1<<c->chrDstVSubSample) - 1), dstH-1)];
  
          //Do horizontal scaling
          while(lastInLumBuf < lastLumSrcY) {
-             const uint8_t *src1= src[0]+(lastInLumBuf + 1 - srcSliceY)*srcStride[0];
-             const uint8_t *src2= src[1]+(lastInLumBuf + 1 - srcSliceY)*srcStride[1];
-             const uint8_t *src3= src[2]+(lastInLumBuf + 1 - srcSliceY)*srcStride[2];
-             const uint8_t *src4= src[3]+(lastInLumBuf + 1 - srcSliceY)*srcStride[3];
+             const uint8_t *src1[4] = {
+                 src[0] + (lastInLumBuf + 1 - srcSliceY) * srcStride[0],
+                 src[1] + (lastInLumBuf + 1 - srcSliceY) * srcStride[1],
+                 src[2] + (lastInLumBuf + 1 - srcSliceY) * srcStride[2],
+                 src[3] + (lastInLumBuf + 1 - srcSliceY) * srcStride[3],
+             };
              lumBufIndex++;
              assert(lumBufIndex < 2*vLumBufSize);
              assert(lastInLumBuf + 1 - srcSliceY < srcSliceH);
              assert(lastInLumBuf + 1 - srcSliceY >= 0);
-             hyscale(c, lumPixBuf[ lumBufIndex ], dstW, src1, src2, src3, srcW, lumXInc,
+             hyscale(c, lumPixBuf[ lumBufIndex ], dstW, src1, srcW, lumXInc,
                      hLumFilter, hLumFilterPos, hLumFilterSize,
                      formatConvBuffer,
                      pal, 0);
              if (CONFIG_SWSCALE_ALPHA && alpPixBuf)
-                 hyscale(c, alpPixBuf[ lumBufIndex ], dstW, src4, NULL, NULL, srcW,
+                 hyscale(c, alpPixBuf[ lumBufIndex ], dstW, src1, srcW,
                          lumXInc, hLumFilter, hLumFilterPos, hLumFilterSize,
                          formatConvBuffer,
                          pal, 1);
                                 lumBufIndex,    lastInLumBuf);
          }
          while(lastInChrBuf < lastChrSrcY) {
-             const uint8_t *src0= src[0]+(lastInChrBuf + 1 - chrSrcSliceY)*srcStride[0];
-             const uint8_t *src1= src[1]+(lastInChrBuf + 1 - chrSrcSliceY)*srcStride[1];
-             const uint8_t *src2= src[2]+(lastInChrBuf + 1 - chrSrcSliceY)*srcStride[2];
+             const uint8_t *src1[4] = {
+                 src[0] + (lastInChrBuf + 1 - chrSrcSliceY) * srcStride[0],
+                 src[1] + (lastInChrBuf + 1 - chrSrcSliceY) * srcStride[1],
+                 src[2] + (lastInChrBuf + 1 - chrSrcSliceY) * srcStride[2],
+                 src[3] + (lastInChrBuf + 1 - chrSrcSliceY) * srcStride[3],
+             };
              chrBufIndex++;
              assert(chrBufIndex < 2*vChrBufSize);
              assert(lastInChrBuf + 1 - chrSrcSliceY < (chrSrcSliceH));
  
              if (c->needs_hcscale)
                  hcscale(c, chrUPixBuf[chrBufIndex], chrVPixBuf[chrBufIndex],
-                           chrDstW, src0, src1, src2, chrSrcW, chrXInc,
+                           chrDstW, src1, chrSrcW, chrXInc,
                            hChrFilter, hChrFilterPos, hChrFilterSize,
                            formatConvBuffer, pal);
              lastInChrBuf++;
              // hmm looks like we can't use MMX here without overwriting this array's tail
              find_c_packed_planar_out_funcs(c, &yuv2plane1, &yuv2planeX,  &yuv2nv12cX,
                                             &yuv2packed1, &yuv2packed2, &yuv2packedX);
 +            use_mmx_vfilter= 0;
          }
  
          {
              const int16_t **chrUSrcPtr= (const int16_t **) chrUPixBuf + chrBufIndex + firstChrSrcY - lastInChrBuf + vChrBufSize;
              const int16_t **chrVSrcPtr= (const int16_t **) chrVPixBuf + chrBufIndex + firstChrSrcY - lastInChrBuf + vChrBufSize;
              const int16_t **alpSrcPtr= (CONFIG_SWSCALE_ALPHA && alpPixBuf) ? (const int16_t **) alpPixBuf + lumBufIndex + firstLumSrcY - lastInLumBuf + vLumBufSize : NULL;
 +            int16_t *vLumFilter= c->vLumFilter;
 +            int16_t *vChrFilter= c->vChrFilter;
 +
              if (isPlanarYUV(dstFormat) || dstFormat==PIX_FMT_GRAY8) { //YV12 like
                  const int chrSkipMask= (1<<c->chrDstVSubSample)-1;
  
 +                vLumFilter +=    dstY * vLumFilterSize;
 +                vChrFilter += chrDstY * vChrFilterSize;
 +
 +                av_assert0(use_mmx_vfilter != (
 +                               yuv2planeX == yuv2planeX_10BE_c
 +                            || yuv2planeX == yuv2planeX_10LE_c
 +                            || yuv2planeX == yuv2planeX_9BE_c
 +                            || yuv2planeX == yuv2planeX_9LE_c
 +                            || yuv2planeX == yuv2planeX_16BE_c
 +                            || yuv2planeX == yuv2planeX_16LE_c
 +                            || yuv2planeX == yuv2planeX_8_c) || !ARCH_X86);
 +
 +                if(use_mmx_vfilter){
 +                    vLumFilter= c->lumMmxFilter;
 +                    vChrFilter= c->chrMmxFilter;
 +                }
 +
                  if (vLumFilterSize == 1) {
                      yuv2plane1(lumSrcPtr[0], dest[0], dstW, c->lumDither8, 0);
                  } else {
 -                    yuv2planeX(vLumFilter + dstY * vLumFilterSize, vLumFilterSize,
 +                    yuv2planeX(vLumFilter, vLumFilterSize,
                                 lumSrcPtr, dest[0], dstW, c->lumDither8, 0);
                  }
  
                  if (!((dstY&chrSkipMask) || isGray(dstFormat))) {
                      if (yuv2nv12cX) {
 -                        yuv2nv12cX(c, vChrFilter + chrDstY * vChrFilterSize, vChrFilterSize, chrUSrcPtr, chrVSrcPtr, dest[1], chrDstW);
 +                        yuv2nv12cX(c, vChrFilter, vChrFilterSize, chrUSrcPtr, chrVSrcPtr, dest[1], chrDstW);
                      } else if (vChrFilterSize == 1) {
                          yuv2plane1(chrUSrcPtr[0], dest[1], chrDstW, c->chrDither8, 0);
                          yuv2plane1(chrVSrcPtr[0], dest[2], chrDstW, c->chrDither8, 3);
                      } else {
 -                        yuv2planeX(vChrFilter + chrDstY * vChrFilterSize, vChrFilterSize,
 +                        yuv2planeX(vChrFilter, vChrFilterSize,
                                     chrUSrcPtr, dest[1], chrDstW, c->chrDither8, 0);
 -                        yuv2planeX(vChrFilter + chrDstY * vChrFilterSize, vChrFilterSize,
 -                                   chrVSrcPtr, dest[2], chrDstW, c->chrDither8, 3);
 +                        yuv2planeX(vChrFilter, vChrFilterSize,
 +                                   chrVSrcPtr, dest[2], chrDstW, c->chrDither8, use_mmx_vfilter ? (c->uv_offx2 >> 1) : 3);
                      }
                  }
  
                  if (CONFIG_SWSCALE_ALPHA && alpPixBuf){
 +                    if(use_mmx_vfilter){
 +                        vLumFilter= c->alpMmxFilter;
 +                    }
                      if (vLumFilterSize == 1) {
                          yuv2plane1(alpSrcPtr[0], dest[3], dstW, c->lumDither8, 0);
                      } else {
 -                        yuv2planeX(vLumFilter + dstY * vLumFilterSize, vLumFilterSize,
 +                        yuv2planeX(vLumFilter, vLumFilterSize,
                                     alpSrcPtr, dest[3], dstW, c->lumDither8, 0);
                      }
                  }
@@@ -2796,13 -2683,20 +2895,20 @@@ static av_cold void sws_init_swScale_c(
          case PIX_FMT_PAL8     :
          case PIX_FMT_BGR4_BYTE:
          case PIX_FMT_RGB4_BYTE: c->chrToYV12 = palToUV_c; break;
+         case PIX_FMT_GBRP9LE:
+         case PIX_FMT_GBRP10LE:
+         case PIX_FMT_GBRP16LE:  c->readChrPlanar = planar_rgb16le_to_uv; break;
+         case PIX_FMT_GBRP9BE:
+         case PIX_FMT_GBRP10BE:
+         case PIX_FMT_GBRP16BE:  c->readChrPlanar = planar_rgb16be_to_uv; break;
+         case PIX_FMT_GBRP:      c->readChrPlanar = planar_rgb_to_uv; break;
  #if HAVE_BIGENDIAN
          case PIX_FMT_YUV444P9LE:
          case PIX_FMT_YUV422P9LE:
          case PIX_FMT_YUV420P9LE:
          case PIX_FMT_YUV422P10LE:
 -        case PIX_FMT_YUV444P10LE:
          case PIX_FMT_YUV420P10LE:
 +        case PIX_FMT_YUV444P10LE:
          case PIX_FMT_YUV420P16LE:
          case PIX_FMT_YUV422P16LE:
          case PIX_FMT_YUV444P16LE: c->chrToYV12 = bswap16UV_c; break;
          case PIX_FMT_RGB565BE: c->chrToYV12 = rgb16beToUV_half_c; break;
          case PIX_FMT_RGB555LE: c->chrToYV12 = rgb15leToUV_half_c; break;
          case PIX_FMT_RGB555BE: c->chrToYV12 = rgb15beToUV_half_c; break;
 +        case PIX_FMT_GBR24P  : c->chrToYV12 = gbr24pToUV_half_c;  break;
          }
      } else {
          switch(srcFormat) {
          case PIX_FMT_RGB565BE: c->chrToYV12 = rgb16beToUV_c; break;
          case PIX_FMT_RGB555LE: c->chrToYV12 = rgb15leToUV_c; break;
          case PIX_FMT_RGB555BE: c->chrToYV12 = rgb15beToUV_c; break;
-         case PIX_FMT_GBR24P  : c->chrToYV12 = gbr24pToUV_c;  break;
++//        case PIX_FMT_GBR24P  : c->chrToYV12 = gbr24pToUV_c;  break;
          }
      }
  
      c->lumToYV12 = NULL;
      c->alpToYV12 = NULL;
      switch (srcFormat) {
+     case PIX_FMT_GBRP9LE:
+     case PIX_FMT_GBRP10LE:
+     case PIX_FMT_GBRP16LE: c->readLumPlanar = planar_rgb16le_to_y; break;
+     case PIX_FMT_GBRP9BE:
+     case PIX_FMT_GBRP10BE:
+     case PIX_FMT_GBRP16BE: c->readLumPlanar = planar_rgb16be_to_y; break;
+     case PIX_FMT_GBRP:     c->readLumPlanar = planar_rgb_to_y; break;
  #if HAVE_BIGENDIAN
      case PIX_FMT_YUV444P9LE:
      case PIX_FMT_YUV422P9LE:
      case PIX_FMT_YUV420P9LE:
 -    case PIX_FMT_YUV444P10LE:
      case PIX_FMT_YUV422P10LE:
      case PIX_FMT_YUV420P10LE:
 +    case PIX_FMT_YUV444P10LE:
      case PIX_FMT_YUV420P16LE:
      case PIX_FMT_YUV422P16LE:
      case PIX_FMT_YUV444P16LE:
      case PIX_FMT_RGB48LE: c->lumToYV12 = rgb48LEToY_c; break;
      case PIX_FMT_BGR48BE: c->lumToYV12 = bgr48BEToY_c; break;
      case PIX_FMT_BGR48LE: c->lumToYV12 = bgr48LEToY_c; break;
-     case PIX_FMT_GBR24P : c->lumToYV12 = gbr24pToY_c ; break;
++//    case PIX_FMT_GBR24P : c->lumToYV12 = gbr24pToY_c ; break;
      }
      if (c->alpPixBuf) {
          switch (srcFormat) {
          case PIX_FMT_ABGR:
          case PIX_FMT_ARGB:  c->alpToYV12 = abgrToA_c; break;
          case PIX_FMT_Y400A: c->alpToYV12 = uyvyToY_c; break;
 +        case PIX_FMT_PAL8 : c->alpToYV12 = palToA_c; break;
          }
      }
  
 +
      if (c->srcBpc == 8) {
          if (c->dstBpc <= 10) {
              c->hyScale = c->hcScale = hScale8To15_c;
index 42012c222e3d9d9f1459e5b63516934c4d479723,7bfdc7eb6bc464d1823d94b39e49d95582650c33..44ff166e550e0b0eeebfd21976e8125d84ad8997
@@@ -1,20 -1,20 +1,20 @@@
  /*
 - * Copyright (C) 2001-2003 Michael Niedermayer <michaelni@gmx.at>
 + * Copyright (C) 2001-2011 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.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * FFmpeg is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
 - * License along with Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
@@@ -30,6 -30,7 +30,7 @@@
  #include "libavutil/avutil.h"
  #include "libavutil/log.h"
  #include "libavutil/pixfmt.h"
+ #include "libavutil/pixdesc.h"
  
  #define STR(s)         AV_TOSTRING(s) //AV_STRINGIFY is too long
  
@@@ -37,8 -38,6 +38,8 @@@
  
  #define MAX_FILTER_SIZE 256
  
 +#define DITHER1XBPP
 +
  #if HAVE_BIGENDIAN
  #define ALT32_CORR (-1)
  #else
@@@ -348,8 -347,8 +349,8 @@@ typedef struct SwsContext 
  #define V_TEMP                "11*8+4*4*256*2+32"
  #define Y_TEMP                "11*8+4*4*256*2+40"
  #define ALP_MMX_FILTER_OFFSET "11*8+4*4*256*2+48"
 -#define UV_OFF_PX             "11*8+4*4*256*3+48"
 -#define UV_OFF_BYTE           "11*8+4*4*256*3+56"
 +#define UV_OFF                "11*8+4*4*256*3+48"
 +#define UV_OFFx2              "11*8+4*4*256*3+56"
  #define DITHER16              "11*8+4*4*256*3+64"
  #define DITHER32              "11*8+4*4*256*3+80"
  
      // alignment of these values is not necessary, but merely here
      // to maintain the same offset across x8632 and x86-64. Once we
      // use proper offset macros in the asm, they can be removed.
 -    DECLARE_ALIGNED(8, ptrdiff_t, uv_off_px);   ///< offset (in pixels) between u and v planes
 -    DECLARE_ALIGNED(8, ptrdiff_t, uv_off_byte); ///< offset (in bytes) between u and v planes
 +    DECLARE_ALIGNED(8, ptrdiff_t, uv_off); ///< offset (in pixels) between u and v planes
 +    DECLARE_ALIGNED(8, ptrdiff_t, uv_offx2); ///< offset (in bytes) between u and v planes
      DECLARE_ALIGNED(8, uint16_t, dither16)[8];
      DECLARE_ALIGNED(8, uint32_t, dither32)[8];
  
  #if HAVE_VIS
      DECLARE_ALIGNED(8, uint64_t, sparc_coeffs)[10];
  #endif
 +    int use_mmx_vfilter;
  
      /* function pointers for swScale() */
      yuv2planar1_fn yuv2plane1;
      yuv2packed2_fn yuv2packed2;
      yuv2packedX_fn yuv2packedX;
  
 -    void (*lumToYV12)(uint8_t *dst, const uint8_t *src,
 +    void (*lumToYV12)(uint8_t *dst, const uint8_t *src, const uint8_t *src2, const uint8_t *src3,
                        int width, uint32_t *pal); ///< Unscaled conversion of luma plane to YV12 for horizontal scaler.
 -    void (*alpToYV12)(uint8_t *dst, const uint8_t *src,
 +    void (*alpToYV12)(uint8_t *dst, const uint8_t *src, const uint8_t *src2, const uint8_t *src3,
                        int width, uint32_t *pal); ///< Unscaled conversion of alpha plane to YV12 for horizontal scaler.
      void (*chrToYV12)(uint8_t *dstU, uint8_t *dstV,
 -                      const uint8_t *src1, const uint8_t *src2,
 +                      const uint8_t *src1, const uint8_t *src2, const uint8_t *src3,
                        int width, uint32_t *pal); ///< Unscaled conversion of chroma planes to YV12 for horizontal scaler.
+     /**
+       * Functions to read planar input, such as planar RGB, and convert
+       * internally to Y/UV.
+       */
+     /** @{ */
+     void (*readLumPlanar)(uint8_t *dst, const uint8_t *src[4], int width);
+     void (*readChrPlanar)(uint8_t *dstU, uint8_t *dstV, const uint8_t *src[4], int width);
+     /** @} */
      /**
       * Scale one horizontal line of input data using a bilinear filter
       * to produce one line of output data. Compared to SwsContext->hScale(),
@@@ -521,111 -529,45 +532,54 @@@ SwsFunc ff_yuv2rgb_init_altivec(SwsCont
  SwsFunc ff_yuv2rgb_get_func_ptr_bfin(SwsContext *c);
  void ff_bfin_get_unscaled_swscale(SwsContext *c);
  
 +#if FF_API_SWS_FORMAT_NAME
 +/**
 + * @deprecated Use av_get_pix_fmt_name() instead.
 + */
 +attribute_deprecated
  const char *sws_format_name(enum PixelFormat format);
 +#endif
  
- //FIXME replace this with something faster
- #define is16BPS(x)      (           \
-            (x)==PIX_FMT_GRAY16BE    \
-         || (x)==PIX_FMT_GRAY16LE    \
-         || (x)==PIX_FMT_BGR48BE     \
-         || (x)==PIX_FMT_BGR48LE     \
-         || (x)==PIX_FMT_RGB48BE     \
-         || (x)==PIX_FMT_RGB48LE     \
-         || (x)==PIX_FMT_BGRA64BE    \
-         || (x)==PIX_FMT_BGRA64LE    \
-         || (x)==PIX_FMT_RGBA64BE    \
-         || (x)==PIX_FMT_RGBA64LE    \
-         || (x)==PIX_FMT_YUV420P16LE \
-         || (x)==PIX_FMT_YUV422P16LE \
-         || (x)==PIX_FMT_YUV444P16LE \
-         || (x)==PIX_FMT_YUV420P16BE \
-         || (x)==PIX_FMT_YUV422P16BE \
-         || (x)==PIX_FMT_YUV444P16BE \
-     )
- #define isNBPS(x)       (           \
-            (x)==PIX_FMT_YUV420P9LE  \
-         || (x)==PIX_FMT_YUV420P9BE  \
-         || (x)==PIX_FMT_YUV422P9LE  \
-         || (x)==PIX_FMT_YUV422P9BE  \
-         || (x)==PIX_FMT_YUV444P9BE  \
-         || (x)==PIX_FMT_YUV444P9LE  \
-         || (x)==PIX_FMT_YUV422P10BE \
-         || (x)==PIX_FMT_YUV422P10LE \
-         || (x)==PIX_FMT_YUV444P10BE \
-         || (x)==PIX_FMT_YUV444P10LE \
-         || (x)==PIX_FMT_YUV420P10LE \
-         || (x)==PIX_FMT_YUV420P10BE \
-         || (x)==PIX_FMT_YUV422P10LE \
-         || (x)==PIX_FMT_YUV422P10BE \
-     )
- #define is9_OR_10BPS isNBPS //for ronald
- #define isBE(x) ((x)&1)
- #define isPlanar8YUV(x) (           \
-            (x)==PIX_FMT_YUV410P     \
-         || (x)==PIX_FMT_YUV420P     \
-         || (x)==PIX_FMT_YUVA420P    \
-         || (x)==PIX_FMT_YUV411P     \
-         || (x)==PIX_FMT_YUV422P     \
-         || (x)==PIX_FMT_YUV444P     \
-         || (x)==PIX_FMT_YUV440P     \
-         || (x)==PIX_FMT_NV12        \
-         || (x)==PIX_FMT_NV21        \
-     )
- #define isPlanarYUV(x)  (           \
-         isPlanar8YUV(x)             \
-         || (x)==PIX_FMT_YUV420P9LE  \
-         || (x)==PIX_FMT_YUV422P9LE  \
-         || (x)==PIX_FMT_YUV444P9LE  \
-         || (x)==PIX_FMT_YUV420P10LE \
-         || (x)==PIX_FMT_YUV422P10LE \
-         || (x)==PIX_FMT_YUV444P10LE \
-         || (x)==PIX_FMT_YUV420P16LE \
-         || (x)==PIX_FMT_YUV422P10LE \
-         || (x)==PIX_FMT_YUV422P16LE \
-         || (x)==PIX_FMT_YUV444P16LE \
-         || (x)==PIX_FMT_YUV420P9BE  \
-         || (x)==PIX_FMT_YUV422P9BE  \
-         || (x)==PIX_FMT_YUV444P9BE  \
-         || (x)==PIX_FMT_YUV420P10BE \
-         || (x)==PIX_FMT_YUV422P10BE \
-         || (x)==PIX_FMT_YUV444P10BE \
-         || (x)==PIX_FMT_YUV420P16BE \
-         || (x)==PIX_FMT_YUV422P10BE \
-         || (x)==PIX_FMT_YUV422P16BE \
-         || (x)==PIX_FMT_YUV444P16BE \
-     )
+ #define is16BPS(x) \
+     (av_pix_fmt_descriptors[x].comp[0].depth_minus1 == 15)
  
- #define isPlanar(x)  (              \
-         isPlanarYUV(x)              \
-         ||  (x)==PIX_FMT_GBR24P     \
-     )
+ #define is9_OR_10BPS(x) \
+     (av_pix_fmt_descriptors[x].comp[0].depth_minus1 == 8 || \
+      av_pix_fmt_descriptors[x].comp[0].depth_minus1 == 9)
  
- #define isYUV(x)        (           \
-            (x)==PIX_FMT_UYVY422     \
-         || (x)==PIX_FMT_YUYV422     \
-         || isPlanarYUV(x)           \
-     )
++#define isNBPS(x) is9_OR_10BPS(x)
++
+ #define isBE(x) \
+     (av_pix_fmt_descriptors[x].flags & PIX_FMT_BE)
+ #define isYUV(x) \
+     (!(av_pix_fmt_descriptors[x].flags & PIX_FMT_RGB) && \
+      av_pix_fmt_descriptors[x].nb_components >= 2)
+ #define isPlanarYUV(x) \
+     ((av_pix_fmt_descriptors[x].flags & PIX_FMT_PLANAR) && \
+      isYUV(x))
+ #define isRGB(x) \
+     (av_pix_fmt_descriptors[x].flags & PIX_FMT_RGB)
 -
+ #if 0 // FIXME
+ #define isGray(x) \
+     (!(av_pix_fmt_descriptors[x].flags & PIX_FMT_PAL) && \
+      av_pix_fmt_descriptors[x].nb_components <= 2)
+ #else
  #define isGray(x)       (           \
             (x)==PIX_FMT_GRAY8       \
 -        || (x)==PIX_FMT_Y400A      \
 +        || (x)==PIX_FMT_GRAY8A      \
          || (x)==PIX_FMT_GRAY16BE    \
          || (x)==PIX_FMT_GRAY16LE    \
      )
- #define isGray16(x)     (           \
-            (x)==PIX_FMT_GRAY16BE    \
-         || (x)==PIX_FMT_GRAY16LE    \
-     )
+ #endif
  #define isRGBinInt(x)   (           \
             (x)==PIX_FMT_RGB48BE     \
          || (x)==PIX_FMT_RGB48LE     \
 +        || (x)==PIX_FMT_RGBA64BE    \
 +        || (x)==PIX_FMT_RGBA64LE    \
          || (x)==PIX_FMT_RGB32       \
          || (x)==PIX_FMT_RGB32_1     \
          || (x)==PIX_FMT_RGB24       \
  #define isBGRinInt(x)   (           \
             (x)==PIX_FMT_BGR48BE     \
          || (x)==PIX_FMT_BGR48LE     \
 +        || (x)==PIX_FMT_BGRA64BE    \
 +        || (x)==PIX_FMT_BGRA64LE    \
          || (x)==PIX_FMT_BGR32       \
          || (x)==PIX_FMT_BGR32_1     \
          || (x)==PIX_FMT_BGR24       \
          || (x)==PIX_FMT_MONOBLACK   \
          || (x)==PIX_FMT_MONOWHITE   \
      )
++
 +#define isRGBinBytes(x) (           \
 +           (x)==PIX_FMT_RGB48BE     \
 +        || (x)==PIX_FMT_RGB48LE     \
 +        || (x)==PIX_FMT_RGBA64BE    \
 +        || (x)==PIX_FMT_RGBA64LE    \
 +        || (x)==PIX_FMT_RGBA        \
 +        || (x)==PIX_FMT_ARGB        \
 +        || (x)==PIX_FMT_RGB24       \
 +    )
 +#define isBGRinBytes(x) (           \
 +           (x)==PIX_FMT_BGR48BE     \
 +        || (x)==PIX_FMT_BGR48LE     \
 +        || (x)==PIX_FMT_BGRA64BE    \
 +        || (x)==PIX_FMT_BGRA64LE    \
 +        || (x)==PIX_FMT_BGRA        \
 +        || (x)==PIX_FMT_ABGR        \
 +        || (x)==PIX_FMT_BGR24       \
 +    )
++
  #define isAnyRGB(x)     (           \
              isRGBinInt(x)           \
          ||  isBGRinInt(x)           \
 +        ||  (x)==PIX_FMT_GBR24P     \
      )
- #define isALPHA(x)      (           \
-            (x)==PIX_FMT_BGRA64BE    \
-         || (x)==PIX_FMT_BGRA64LE    \
-         || (x)==PIX_FMT_RGBA64BE    \
-         || (x)==PIX_FMT_RGBA64LE    \
-         || (x)==PIX_FMT_BGR32       \
-         || (x)==PIX_FMT_BGR32_1     \
-         || (x)==PIX_FMT_RGB32       \
-         || (x)==PIX_FMT_RGB32_1     \
-         || (x)==PIX_FMT_PAL8        \
-         || (x)==PIX_FMT_GRAY8A      \
-         || (x)==PIX_FMT_YUVA420P    \
-     )
++
+ #define isALPHA(x) \
+     (av_pix_fmt_descriptors[x].nb_components == 2 || \
+      av_pix_fmt_descriptors[x].nb_components == 4)
++#if 1
 +#define isPacked(x)         (       \
 +           (x)==PIX_FMT_PAL8        \
 +        || (x)==PIX_FMT_YUYV422     \
 +        || (x)==PIX_FMT_UYVY422     \
 +        || (x)==PIX_FMT_Y400A       \
 +        ||  isRGBinInt(x)           \
 +        ||  isBGRinInt(x)           \
 +    )
- #define usePal(x) ((av_pix_fmt_descriptors[x].flags & PIX_FMT_PAL) || (x) == PIX_FMT_GRAY8A)
++#else
+ #define isPacked(x) \
+     (av_pix_fmt_descriptors[x].nb_components >= 2 && \
+      !(av_pix_fmt_descriptors[x].flags & PIX_FMT_PLANAR))
++#endif
+ #define isPlanar(x) \
+     (av_pix_fmt_descriptors[x].nb_components >= 2 && \
+      (av_pix_fmt_descriptors[x].flags & PIX_FMT_PLANAR))
+ #define usePal(x) ((av_pix_fmt_descriptors[x].flags & PIX_FMT_PAL) || (x) == PIX_FMT_Y400A)
  
  extern const uint64_t ff_dither4[2];
  extern const uint64_t ff_dither8[2];
 +extern const uint8_t dithers[8][8][8];
 +extern const uint16_t dither_scale[15][16];
 +
  
  extern const AVClass sws_context_class;
  
index adeb409d2f231b1e08ab9d85ddaa129d4ca1c33b,86bc5acda653a1e6512cde982b603a81cbbd7e65..80ae5fc287004607b2ac6ab433d89f89053dd11a
@@@ -1,20 -1,20 +1,20 @@@
  /*
 - * Copyright (C) 2001-2003 Michael Niedermayer <michaelni@gmx.at>
 + * Copyright (C) 2001-2011 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.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * FFmpeg is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
 - * License along with Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
  #include "libavutil/bswap.h"
  #include "libavutil/pixdesc.h"
  
 -DECLARE_ALIGNED(8, const uint8_t, dither_8x8_1)[8][8] = {
 -    {   0,  1,  0,  1,  0,  1,  0,  1,},
 -    {   1,  0,  1,  0,  1,  0,  1,  0,},
 -    {   0,  1,  0,  1,  0,  1,  0,  1,},
 -    {   1,  0,  1,  0,  1,  0,  1,  0,},
 -    {   0,  1,  0,  1,  0,  1,  0,  1,},
 -    {   1,  0,  1,  0,  1,  0,  1,  0,},
 -    {   0,  1,  0,  1,  0,  1,  0,  1,},
 -    {   1,  0,  1,  0,  1,  0,  1,  0,},
 -};
 -DECLARE_ALIGNED(8, const uint8_t, dither_8x8_3)[8][8] = {
 -    {   1,  2,  1,  2,  1,  2,  1,  2,},
 -    {   3,  0,  3,  0,  3,  0,  3,  0,},
 -    {   1,  2,  1,  2,  1,  2,  1,  2,},
 -    {   3,  0,  3,  0,  3,  0,  3,  0,},
 -    {   1,  2,  1,  2,  1,  2,  1,  2,},
 -    {   3,  0,  3,  0,  3,  0,  3,  0,},
 -    {   1,  2,  1,  2,  1,  2,  1,  2,},
 -    {   3,  0,  3,  0,  3,  0,  3,  0,},
 -};
 -DECLARE_ALIGNED(8, const uint8_t, dither_8x8_64)[8][8] = {
 -    {  18, 34, 30, 46, 17, 33, 29, 45,},
 -    {  50,  2, 62, 14, 49,  1, 61, 13,},
 -    {  26, 42, 22, 38, 25, 41, 21, 37,},
 -    {  58, 10, 54,  6, 57,  9, 53,  5,},
 -    {  16, 32, 28, 44, 19, 35, 31, 47,},
 -    {  48,  0, 60, 12, 51,  3, 63, 15,},
 -    {  24, 40, 20, 36, 27, 43, 23, 39,},
 -    {  56,  8, 52,  4, 59, 11, 55,  7,},
 -};
 -extern const uint8_t dither_8x8_128[8][8];
 -DECLARE_ALIGNED(8, const uint8_t, dither_8x8_256)[8][8] = {
 -    {  72, 136, 120, 184,  68, 132, 116, 180,},
 -    { 200,   8, 248,  56, 196,   4, 244,  52,},
 -    { 104, 168,  88, 152, 100, 164,  84, 148,},
 -    { 232,  40, 216,  24, 228,  36, 212,  20,},
 -    {  64, 128, 102, 176,  76, 140, 124, 188,},
 -    { 192,   0, 240,  48, 204,  12, 252,  60,},
 -    {  96, 160,  80, 144, 108, 172,  92, 156,},
 -    { 224,  32, 208,  16, 236,  44, 220,  28,},
 -};
 -
  #define RGB2YUV_SHIFT 15
  #define BY ( (int)(0.114*219/255*(1<<RGB2YUV_SHIFT)+0.5))
  #define BV (-(int)(0.081*224/255*(1<<RGB2YUV_SHIFT)+0.5))
@@@ -221,7 -263,7 +221,7 @@@ static int palToRgbWrapper(SwsContext *
      uint8_t *dstPtr= dst[0] + dstStride[0]*srcSliceY;
      const uint8_t *srcPtr= src[0];
  
 -    if (srcFormat == PIX_FMT_Y400A) {
 +    if (srcFormat == PIX_FMT_GRAY8A) {
          switch (dstFormat) {
          case PIX_FMT_RGB32  : conv = gray8aToPacked32; break;
          case PIX_FMT_BGR32  : conv = gray8aToPacked32; break;
  
      if (!conv)
          av_log(c, AV_LOG_ERROR, "internal error %s -> %s converter\n",
 -               sws_format_name(srcFormat), sws_format_name(dstFormat));
 +               av_get_pix_fmt_name(srcFormat), av_get_pix_fmt_name(dstFormat));
      else {
          for (i=0; i<srcSliceH; i++) {
              conv(srcPtr, dstPtr, c->srcW, (uint8_t *) c->pal_rgb);
      return srcSliceH;
  }
  
 +static void gbr24ptopacked24(const uint8_t* src[], int srcStride[], uint8_t* dst, int dstStride, int srcSliceH, int width)
 +{
 +    int x, h, i;
 +    for (h = 0; h < srcSliceH; h++) {
 +        uint8_t *dest = dst + dstStride * h;
 +        for (x = 0; x < width; x++) {
 +            *dest++ = src[0][x];
 +            *dest++ = src[1][x];
 +            *dest++ = src[2][x];
 +        }
 +
 +        for (i = 0; i < 3; i++)
 +            src[i] += srcStride[i];
 +    }
 +}
 +
 +static void gbr24ptopacked32(const uint8_t* src[], int srcStride[], uint8_t* dst, int dstStride, int srcSliceH, int alpha_first, int width)
 +{
 +    int x, h, i;
 +    for (h = 0; h < srcSliceH; h++) {
 +        uint8_t *dest = dst + dstStride * h;
 +
 +        if (alpha_first) {
 +            for (x = 0; x < width; x++) {
 +                *dest++ = 0xff;
 +                *dest++ = src[0][x];
 +                *dest++ = src[1][x];
 +                *dest++ = src[2][x];
 +            }
 +        } else {
 +            for (x = 0; x < width; x++) {
 +                *dest++ = src[0][x];
 +                *dest++ = src[1][x];
 +                *dest++ = src[2][x];
 +                *dest++ = 0xff;
 +            }
 +        }
 +
 +        for (i = 0; i < 3; i++)
 +            src[i] += srcStride[i];
 +    }
 +}
 +
 +static int planarRgbToRgbWrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
 +        int srcSliceH, uint8_t* dst[], int dstStride[])
 +{
 +    int alpha_first = 0;
 +    if (c->srcFormat != PIX_FMT_GBR24P) {
 +        av_log(c, AV_LOG_ERROR, "unsupported planar RGB conversion %s -> %s\n",
 +              av_get_pix_fmt_name(c->srcFormat), av_get_pix_fmt_name(c->dstFormat));
 +        return srcSliceH;
 +    }
 +
 +    switch (c->dstFormat) {
 +        case PIX_FMT_BGR24:
 +            gbr24ptopacked24((const uint8_t* []) {src[1], src[0], src[2]}, (int []) {srcStride[1], srcStride[0], srcStride[2]},
 +                  dst[0] + srcSliceY * dstStride[0], dstStride[0], srcSliceH, c->srcW);
 +            break;
 +
 +        case PIX_FMT_RGB24:
 +            gbr24ptopacked24((const uint8_t* []) {src[2], src[0], src[1]}, (int []) {srcStride[2], srcStride[0], srcStride[1]},
 +                  dst[0] + srcSliceY * dstStride[0], dstStride[0], srcSliceH, c->srcW);
 +            break;
 +
 +        case PIX_FMT_ARGB:
 +            alpha_first = 1;
 +        case PIX_FMT_RGBA:
 +            gbr24ptopacked32((const uint8_t* []) {src[2], src[0], src[1]}, (int []) {srcStride[2], srcStride[0], srcStride[1]},
 +                  dst[0] + srcSliceY * dstStride[0], dstStride[0], srcSliceH, alpha_first, c->srcW);
 +            break;
 +
 +        case PIX_FMT_ABGR:
 +            alpha_first = 1;
 +        case PIX_FMT_BGRA:
 +            gbr24ptopacked32((const uint8_t* []) {src[1], src[0], src[2]}, (int []) {srcStride[1], srcStride[0], srcStride[2]},
 +                  dst[0] + srcSliceY * dstStride[0], dstStride[0], srcSliceH, alpha_first, c->srcW);
 +            break;
 +
 +        default:
 +            av_log(c, AV_LOG_ERROR, "unsupported planar RGB conversion %s -> %s\n",
 +                    av_get_pix_fmt_name(c->srcFormat), av_get_pix_fmt_name(c->dstFormat));
 +    }
 +
 +    return srcSliceH;
 +}
 +
  #define isRGBA32(x) (            \
             (x) == PIX_FMT_ARGB   \
          || (x) == PIX_FMT_RGBA   \
@@@ -416,7 -372,7 +416,7 @@@ static int rgbToRgbWrapper(SwsContext *
  
      if (!conv) {
          av_log(c, AV_LOG_ERROR, "internal error %s -> %s converter\n",
 -               sws_format_name(srcFormat), sws_format_name(dstFormat));
 +               av_get_pix_fmt_name(srcFormat), av_get_pix_fmt_name(dstFormat));
      } else {
          const uint8_t *srcPtr= src[0];
                uint8_t *dstPtr= dst[0];
@@@ -498,28 -454,27 +498,28 @@@ static int packedCopyWrapper(SwsContex
      return srcSliceH;
  }
  
 -#define clip9(x)  av_clip_uintp2(x,  9)
 -#define clip10(x) av_clip_uintp2(x, 10)
 -#define DITHER_COPY(dst, dstStride, wfunc, src, srcStride, rfunc, dithers, shift, clip) \
 -    for (i = 0; i < height; i++) { \
 -        const uint8_t *dither = dithers[i & 7]; \
 -        for (j = 0; j < length - 7; j += 8) { \
 -            wfunc(&dst[j + 0], clip((rfunc(&src[j + 0]) + dither[0]) >> shift)); \
 -            wfunc(&dst[j + 1], clip((rfunc(&src[j + 1]) + dither[1]) >> shift)); \
 -            wfunc(&dst[j + 2], clip((rfunc(&src[j + 2]) + dither[2]) >> shift)); \
 -            wfunc(&dst[j + 3], clip((rfunc(&src[j + 3]) + dither[3]) >> shift)); \
 -            wfunc(&dst[j + 4], clip((rfunc(&src[j + 4]) + dither[4]) >> shift)); \
 -            wfunc(&dst[j + 5], clip((rfunc(&src[j + 5]) + dither[5]) >> shift)); \
 -            wfunc(&dst[j + 6], clip((rfunc(&src[j + 6]) + dither[6]) >> shift)); \
 -            wfunc(&dst[j + 7], clip((rfunc(&src[j + 7]) + dither[7]) >> shift)); \
 -        } \
 -        for (; j < length; j++) \
 -            wfunc(&dst[j],     (rfunc(&src[j]) + dither[j & 7]) >> shift); \
 -        dst += dstStride; \
 -        src += srcStride; \
 +#define DITHER_COPY(dst, dstStride, src, srcStride, bswap, dbswap)\
 +    uint16_t scale= dither_scale[dst_depth-1][src_depth-1];\
 +    int shift= src_depth-dst_depth + dither_scale[src_depth-2][dst_depth-1];\
 +    for (i = 0; i < height; i++) {\
 +        const uint8_t *dither= dithers[src_depth-9][i&7];\
 +        for (j = 0; j < length-7; j+=8){\
 +            dst[j+0] = dbswap((bswap(src[j+0]) + dither[0])*scale>>shift);\
 +            dst[j+1] = dbswap((bswap(src[j+1]) + dither[1])*scale>>shift);\
 +            dst[j+2] = dbswap((bswap(src[j+2]) + dither[2])*scale>>shift);\
 +            dst[j+3] = dbswap((bswap(src[j+3]) + dither[3])*scale>>shift);\
 +            dst[j+4] = dbswap((bswap(src[j+4]) + dither[4])*scale>>shift);\
 +            dst[j+5] = dbswap((bswap(src[j+5]) + dither[5])*scale>>shift);\
 +            dst[j+6] = dbswap((bswap(src[j+6]) + dither[6])*scale>>shift);\
 +            dst[j+7] = dbswap((bswap(src[j+7]) + dither[7])*scale>>shift);\
 +        }\
 +        for (; j < length; j++)\
 +            dst[j] = dbswap((bswap(src[j]) + dither[j&7])*scale>>shift);\
 +        dst += dstStride;\
 +        src += srcStride;\
      }
  
 +
  static int planarCopyWrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
                               int srcSliceH, uint8_t* dst[], int dstStride[])
  {
          int height= (plane==0 || plane==3) ? srcSliceH: -((-srcSliceH)>>c->chrDstVSubSample);
          const uint8_t *srcPtr= src[plane];
          uint8_t *dstPtr= dst[plane] + dstStride[plane]*y;
 +        int shiftonly= plane==1 || plane==2 || (!c->srcRange && plane==0);
  
          if (!dst[plane]) continue;
          // ignore palette for GRAY8
                  length*=2;
              fillPlane(dst[plane], dstStride[plane], length, height, y, (plane==3) ? 255 : 128);
          } else {
 -            if(is9_OR_10BPS(c->srcFormat)) {
 +            if(isNBPS(c->srcFormat) || isNBPS(c->dstFormat)
 +               || (is16BPS(c->srcFormat) != is16BPS(c->dstFormat))
 +            ) {
                  const int src_depth = av_pix_fmt_descriptors[c->srcFormat].comp[plane].depth_minus1+1;
                  const int dst_depth = av_pix_fmt_descriptors[c->dstFormat].comp[plane].depth_minus1+1;
                  const uint16_t *srcPtr2 = (const uint16_t*)srcPtr;
 +                uint16_t *dstPtr2 = (uint16_t*)dstPtr;
  
 -                if (is16BPS(c->dstFormat)) {
 -                    uint16_t *dstPtr2 = (uint16_t*)dstPtr;
 -#define COPY9_OR_10TO16(rfunc, wfunc) \
 -                    for (i = 0; i < height; i++) { \
 -                        for (j = 0; j < length; j++) { \
 -                            int srcpx = rfunc(&srcPtr2[j]); \
 -                            wfunc(&dstPtr2[j], (srcpx<<(16-src_depth)) | (srcpx>>(2*src_depth-16))); \
 -                        } \
 -                        dstPtr2 += dstStride[plane]/2; \
 -                        srcPtr2 += srcStride[plane]/2; \
 +                if (dst_depth == 8) {
 +                    if(isBE(c->srcFormat) == HAVE_BIGENDIAN){
 +                        DITHER_COPY(dstPtr, dstStride[plane], srcPtr2, srcStride[plane]/2, , )
 +                    } else {
 +                        DITHER_COPY(dstPtr, dstStride[plane], srcPtr2, srcStride[plane]/2, av_bswap16, )
                      }
 -                    if (isBE(c->dstFormat)) {
 -                        if (isBE(c->srcFormat)) {
 -                            COPY9_OR_10TO16(AV_RB16, AV_WB16);
 -                        } else {
 -                            COPY9_OR_10TO16(AV_RL16, AV_WB16);
 +                } else if (src_depth == 8) {
 +                    for (i = 0; i < height; i++) {
 +                        #define COPY816(w)\
 +                        if(shiftonly){\
 +                            for (j = 0; j < length; j++)\
 +                                w(&dstPtr2[j], srcPtr[j]<<(dst_depth-8));\
 +                        }else{\
 +                            for (j = 0; j < length; j++)\
 +                                w(&dstPtr2[j], (srcPtr[j]<<(dst_depth-8)) |\
 +                                               (srcPtr[j]>>(2*8-dst_depth)));\
                          }
 -                    } else {
 -                        if (isBE(c->srcFormat)) {
 -                            COPY9_OR_10TO16(AV_RB16, AV_WL16);
 +                        if(isBE(c->dstFormat)){
 +                            COPY816(AV_WB16)
                          } else {
 -                            COPY9_OR_10TO16(AV_RL16, AV_WL16);
 +                            COPY816(AV_WL16)
                          }
 +                        dstPtr2 += dstStride[plane]/2;
 +                        srcPtr  += srcStride[plane];
                      }
 -                } else if (is9_OR_10BPS(c->dstFormat)) {
 -                    uint16_t *dstPtr2 = (uint16_t*)dstPtr;
 -#define COPY9_OR_10TO9_OR_10(loop) \
 -                    for (i = 0; i < height; i++) { \
 -                        for (j = 0; j < length; j++) { \
 -                            loop; \
 -                        } \
 -                        dstPtr2 += dstStride[plane]/2; \
 -                        srcPtr2 += srcStride[plane]/2; \
 -                    }
 -#define COPY9_OR_10TO9_OR_10_2(rfunc, wfunc) \
 -                    if (dst_depth > src_depth) { \
 -                        COPY9_OR_10TO9_OR_10(int srcpx = rfunc(&srcPtr2[j]); \
 -                            wfunc(&dstPtr2[j], (srcpx << 1) | (srcpx >> 9))); \
 -                    } else if (dst_depth < src_depth) { \
 -                        DITHER_COPY(dstPtr2, dstStride[plane]/2, wfunc, \
 -                                    srcPtr2, srcStride[plane]/2, rfunc, \
 -                                    dither_8x8_1, 1, clip9); \
 -                    } else { \
 -                        COPY9_OR_10TO9_OR_10(wfunc(&dstPtr2[j], rfunc(&srcPtr2[j]))); \
 -                    }
 -                    if (isBE(c->dstFormat)) {
 -                        if (isBE(c->srcFormat)) {
 -                            COPY9_OR_10TO9_OR_10_2(AV_RB16, AV_WB16);
 -                        } else {
 -                            COPY9_OR_10TO9_OR_10_2(AV_RL16, AV_WB16);
 -                        }
 -                    } else {
 -                        if (isBE(c->srcFormat)) {
 -                            COPY9_OR_10TO9_OR_10_2(AV_RB16, AV_WL16);
 +                } else if (src_depth <= dst_depth) {
 +                    for (i = 0; i < height; i++) {
 +#define COPY_UP(r,w) \
 +    if(shiftonly){\
 +        for (j = 0; j < length; j++){ \
 +            unsigned int v= r(&srcPtr2[j]);\
 +            w(&dstPtr2[j], v<<(dst_depth-src_depth));\
 +        }\
 +    }else{\
 +        for (j = 0; j < length; j++){ \
 +            unsigned int v= r(&srcPtr2[j]);\
 +            w(&dstPtr2[j], (v<<(dst_depth-src_depth)) | \
 +                        (v>>(2*src_depth-dst_depth)));\
 +        }\
 +    }
 +                        if(isBE(c->srcFormat)){
 +                            if(isBE(c->dstFormat)){
 +                                COPY_UP(AV_RB16, AV_WB16)
 +                            } else {
 +                                COPY_UP(AV_RB16, AV_WL16)
 +                            }
                          } else {
 -                            COPY9_OR_10TO9_OR_10_2(AV_RL16, AV_WL16);
 +                            if(isBE(c->dstFormat)){
 +                                COPY_UP(AV_RL16, AV_WB16)
 +                            } else {
 +                                COPY_UP(AV_RL16, AV_WL16)
 +                            }
                          }
 +                        dstPtr2 += dstStride[plane]/2;
 +                        srcPtr2 += srcStride[plane]/2;
                      }
                  } else {
 -#define W8(a, b) { *(a) = (b); }
 -#define COPY9_OR_10TO8(rfunc) \
 -                    if (src_depth == 9) { \
 -                        DITHER_COPY(dstPtr,  dstStride[plane],   W8, \
 -                                    srcPtr2, srcStride[plane]/2, rfunc, \
 -                                    dither_8x8_1, 1, av_clip_uint8); \
 -                    } else { \
 -                        DITHER_COPY(dstPtr,  dstStride[plane],   W8, \
 -                                    srcPtr2, srcStride[plane]/2, rfunc, \
 -                                    dither_8x8_3, 2, av_clip_uint8); \
 -                    }
 -                    if (isBE(c->srcFormat)) {
 -                        COPY9_OR_10TO8(AV_RB16);
 -                    } else {
 -                        COPY9_OR_10TO8(AV_RL16);
 -                    }
 -                }
 -            } else if(is9_OR_10BPS(c->dstFormat)) {
 -                const int dst_depth = av_pix_fmt_descriptors[c->dstFormat].comp[plane].depth_minus1+1;
 -                uint16_t *dstPtr2 = (uint16_t*)dstPtr;
 -
 -                if (is16BPS(c->srcFormat)) {
 -                    const uint16_t *srcPtr2 = (const uint16_t*)srcPtr;
 -#define COPY16TO9_OR_10(rfunc, wfunc) \
 -                    if (dst_depth == 9) { \
 -                        DITHER_COPY(dstPtr2, dstStride[plane]/2, wfunc, \
 -                                    srcPtr2, srcStride[plane]/2, rfunc, \
 -                                    dither_8x8_128, 7, clip9); \
 -                    } else { \
 -                        DITHER_COPY(dstPtr2, dstStride[plane]/2, wfunc, \
 -                                    srcPtr2, srcStride[plane]/2, rfunc, \
 -                                    dither_8x8_64, 6, clip10); \
 -                    }
 -                    if (isBE(c->dstFormat)) {
 -                        if (isBE(c->srcFormat)) {
 -                            COPY16TO9_OR_10(AV_RB16, AV_WB16);
 +                    if(isBE(c->srcFormat) == HAVE_BIGENDIAN){
 +                        if(isBE(c->dstFormat) == HAVE_BIGENDIAN){
 +                            DITHER_COPY(dstPtr2, dstStride[plane]/2, srcPtr2, srcStride[plane]/2, , )
                          } else {
 -                            COPY16TO9_OR_10(AV_RL16, AV_WB16);
 +                            DITHER_COPY(dstPtr2, dstStride[plane]/2, srcPtr2, srcStride[plane]/2, , av_bswap16)
                          }
 -                    } else {
 -                        if (isBE(c->srcFormat)) {
 -                            COPY16TO9_OR_10(AV_RB16, AV_WL16);
 +                    }else{
 +                        if(isBE(c->dstFormat) == HAVE_BIGENDIAN){
 +                            DITHER_COPY(dstPtr2, dstStride[plane]/2, srcPtr2, srcStride[plane]/2, av_bswap16, )
                          } else {
 -                            COPY16TO9_OR_10(AV_RL16, AV_WL16);
 +                            DITHER_COPY(dstPtr2, dstStride[plane]/2, srcPtr2, srcStride[plane]/2, av_bswap16, av_bswap16)
                          }
                      }
 -                } else /* 8bit */ {
 -#define COPY8TO9_OR_10(wfunc) \
 -                    for (i = 0; i < height; i++) { \
 -                        for (j = 0; j < length; j++) { \
 -                            const int srcpx = srcPtr[j]; \
 -                            wfunc(&dstPtr2[j], (srcpx<<(dst_depth-8)) | (srcpx >> (16-dst_depth))); \
 -                        } \
 -                        dstPtr2 += dstStride[plane]/2; \
 -                        srcPtr  += srcStride[plane]; \
 -                    }
 -                    if (isBE(c->dstFormat)) {
 -                        COPY8TO9_OR_10(AV_WB16);
 -                    } else {
 -                        COPY8TO9_OR_10(AV_WL16);
 -                    }
 -                }
 -            } else if(is16BPS(c->srcFormat) && !is16BPS(c->dstFormat)) {
 -                const uint16_t *srcPtr2 = (const uint16_t*)srcPtr;
 -#define COPY16TO8(rfunc) \
 -                    DITHER_COPY(dstPtr,  dstStride[plane],   W8, \
 -                                srcPtr2, srcStride[plane]/2, rfunc, \
 -                                dither_8x8_256, 8, av_clip_uint8);
 -                if (isBE(c->srcFormat)) {
 -                    COPY16TO8(AV_RB16);
 -                } else {
 -                    COPY16TO8(AV_RL16);
 -                }
 -            } else if(!is16BPS(c->srcFormat) && is16BPS(c->dstFormat)) {
 -                for (i=0; i<height; i++) {
 -                    for (j=0; j<length; j++) {
 -                        dstPtr[ j<<1   ] = srcPtr[j];
 -                        dstPtr[(j<<1)+1] = srcPtr[j];
 -                    }
 -                    srcPtr+= srcStride[plane];
 -                    dstPtr+= dstStride[plane];
                  }
              } else if(is16BPS(c->srcFormat) && is16BPS(c->dstFormat)
                    && isBE(c->srcFormat) != isBE(c->dstFormat)) {
@@@ -694,18 -715,13 +694,18 @@@ void ff_get_unscaled_swscale(SwsContex
          && (!needsDither || (c->flags&(SWS_FAST_BILINEAR|SWS_POINT))))
          c->swScale= rgbToRgbWrapper;
  
 -    if ((usePal(srcFormat) && (
 -        dstFormat == PIX_FMT_RGB32   ||
 -        dstFormat == PIX_FMT_RGB32_1 ||
 -        dstFormat == PIX_FMT_RGB24   ||
 -        dstFormat == PIX_FMT_BGR32   ||
 -        dstFormat == PIX_FMT_BGR32_1 ||
 -        dstFormat == PIX_FMT_BGR24)))
 +#define isByteRGB(f) (\
 +        f == PIX_FMT_RGB32   ||\
 +        f == PIX_FMT_RGB32_1 ||\
 +        f == PIX_FMT_RGB24   ||\
 +        f == PIX_FMT_BGR32   ||\
 +        f == PIX_FMT_BGR32_1 ||\
 +        f == PIX_FMT_BGR24)
 +
 +    if (isAnyRGB(srcFormat) && isPlanar(srcFormat) && isByteRGB(dstFormat))
 +        c->swScale= planarRgbToRgbWrapper;
 +
 +    if (usePal(srcFormat) && isByteRGB(dstFormat))
          c->swScale= palToRgbWrapper;
  
      if (srcFormat == PIX_FMT_YUV422P) {
@@@ -763,7 -779,7 +763,7 @@@ static void reset_ptr(const uint8_t* sr
  {
      if(!isALPHA(format))
          src[3]=NULL;
-     if(!isPlanar(format)) {
+     if (!isPlanar(format)) {
          src[3]=src[2]=NULL;
  
          if (!usePal(format))
      }
  }
  
 -static int check_image_pointers(uint8_t *data[4], enum PixelFormat pix_fmt,
 +static int check_image_pointers(const uint8_t * const data[4], enum PixelFormat pix_fmt,
                                  const int linesizes[4])
  {
      const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[pix_fmt];
@@@ -806,7 -822,7 +806,7 @@@ int attribute_align_arg sws_scale(struc
          av_log(c, AV_LOG_ERROR, "bad src image pointers\n");
          return 0;
      }
 -    if (!check_image_pointers(dst, c->dstFormat, dstStride)) {
 +    if (!check_image_pointers((const uint8_t* const*)dst, c->dstFormat, dstStride)) {
          av_log(c, AV_LOG_ERROR, "bad dst image pointers\n");
          return 0;
      }
  
      if (usePal(c->srcFormat)) {
          for (i=0; i<256; i++) {
 -            int p, r, g, b,y,u,v;
 +            int p, r, g, b, y, u, v, a = 0xff;
              if(c->srcFormat == PIX_FMT_PAL8) {
                  p=((const uint32_t*)(srcSlice[1]))[i];
 +                a= (p>>24)&0xFF;
                  r= (p>>16)&0xFF;
                  g= (p>> 8)&0xFF;
                  b=  p     &0xFF;
                  r= (i>>3    )*255;
                  g= ((i>>1)&3)*85;
                  b= (i&1     )*255;
 -            } else if(c->srcFormat == PIX_FMT_GRAY8 || c->srcFormat == PIX_FMT_Y400A) {
 +            } else if(c->srcFormat == PIX_FMT_GRAY8 || c->srcFormat == PIX_FMT_GRAY8A) {
                  r = g = b = i;
              } else {
                  assert(c->srcFormat == PIX_FMT_BGR4_BYTE);
              y= av_clip_uint8((RY*r + GY*g + BY*b + ( 33<<(RGB2YUV_SHIFT-1)))>>RGB2YUV_SHIFT);
              u= av_clip_uint8((RU*r + GU*g + BU*b + (257<<(RGB2YUV_SHIFT-1)))>>RGB2YUV_SHIFT);
              v= av_clip_uint8((RV*r + GV*g + BV*b + (257<<(RGB2YUV_SHIFT-1)))>>RGB2YUV_SHIFT);
 -            c->pal_yuv[i]= y + (u<<8) + (v<<16);
 +            c->pal_yuv[i]= y + (u<<8) + (v<<16) + (a<<24);
  
              switch(c->dstFormat) {
              case PIX_FMT_BGR32:
  #if !HAVE_BIGENDIAN
              case PIX_FMT_RGB24:
  #endif
 -                c->pal_rgb[i]=  r + (g<<8) + (b<<16);
 +                c->pal_rgb[i]=  r + (g<<8) + (b<<16) + (a<<24);
                  break;
              case PIX_FMT_BGR32_1:
  #if HAVE_BIGENDIAN
              case PIX_FMT_BGR24:
  #endif
 -                c->pal_rgb[i]= (r + (g<<8) + (b<<16)) << 8;
 +                c->pal_rgb[i]= a + (r<<8) + (g<<16) + (b<<24);
                  break;
              case PIX_FMT_RGB32_1:
  #if HAVE_BIGENDIAN
              case PIX_FMT_RGB24:
  #endif
 -                c->pal_rgb[i]= (b + (g<<8) + (r<<16)) << 8;
 +                c->pal_rgb[i]= a + (b<<8) + (g<<16) + (r<<24);
                  break;
              case PIX_FMT_RGB32:
  #if !HAVE_BIGENDIAN
              case PIX_FMT_BGR24:
  #endif
              default:
 -                c->pal_rgb[i]=  b + (g<<8) + (r<<16);
 +                c->pal_rgb[i]=  b + (g<<8) + (r<<16) + (a<<24);
              }
          }
      }
          int dstStride2[4]= {dstStride[0], dstStride[1], dstStride[2], dstStride[3]};
  
          reset_ptr(src2, c->srcFormat);
 -        reset_ptr((const uint8_t**)dst2, c->dstFormat);
 +        reset_ptr((void*)dst2, c->dstFormat);
  
          /* reset slice direction at end of frame */
          if (srcSliceY + srcSliceH == c->srcH)
          dst2[3] += ( c->dstH                      -1)*dstStride[3];
  
          reset_ptr(src2, c->srcFormat);
 -        reset_ptr((const uint8_t**)dst2, c->dstFormat);
 +        reset_ptr((void*)dst2, c->dstFormat);
  
          /* reset slice direction at end of frame */
          if (!srcSliceY)
diff --combined libswscale/utils.c
index 7cc13bf7e524e90fa9b805642e879842a69097fb,7a969867edf6b6795f6ab07c2cdfded27984ddb7..347b9905e094c1b43a4ed4c8ee836a5725dab778
@@@ -1,25 -1,23 +1,25 @@@
  /*
   * Copyright (C) 2001-2003 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.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * FFmpeg is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
 - * License along with Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
 +#define _SVID_SOURCE //needed for MAP_ANONYMOUS
 +#define _DARWIN_C_SOURCE // needed for MAP_ANON
  #include <inttypes.h>
  #include <string.h>
  #include <math.h>
@@@ -46,7 -44,6 +46,7 @@@
  #include "libavutil/bswap.h"
  #include "libavutil/opt.h"
  #include "libavutil/pixdesc.h"
 +#include "libavutil/avassert.h"
  
  unsigned swscale_version(void)
  {
  
  const char *swscale_configuration(void)
  {
 -    return LIBAV_CONFIGURATION;
 +    return FFMPEG_CONFIGURATION;
  }
  
  const char *swscale_license(void)
  {
  #define LICENSE_PREFIX "libswscale license: "
 -    return LICENSE_PREFIX LIBAV_LICENSE + sizeof(LICENSE_PREFIX) - 1;
 +    return LICENSE_PREFIX FFMPEG_LICENSE + sizeof(LICENSE_PREFIX) - 1;
  }
  
  #define RET 0xC3 //near return opcode for x86
@@@ -107,8 -104,6 +107,8 @@@ const static FormatEntry format_entries
      [PIX_FMT_YUVA420P]    = { 1 , 1 },
      [PIX_FMT_RGB48BE]     = { 1 , 1 },
      [PIX_FMT_RGB48LE]     = { 1 , 1 },
 +    [PIX_FMT_RGBA64BE]    = { 0 , 0 },
 +    [PIX_FMT_RGBA64LE]    = { 0 , 0 },
      [PIX_FMT_RGB565BE]    = { 1 , 1 },
      [PIX_FMT_RGB565LE]    = { 1 , 1 },
      [PIX_FMT_RGB555BE]    = { 1 , 1 },
      [PIX_FMT_Y400A]       = { 1 , 0 },
      [PIX_FMT_BGR48BE]     = { 1 , 1 },
      [PIX_FMT_BGR48LE]     = { 1 , 1 },
 +    [PIX_FMT_BGRA64BE]    = { 0 , 0 },
 +    [PIX_FMT_BGRA64LE]    = { 0 , 0 },
      [PIX_FMT_YUV420P9BE]  = { 1 , 1 },
      [PIX_FMT_YUV420P9LE]  = { 1 , 1 },
      [PIX_FMT_YUV420P10BE] = { 1 , 1 },
      [PIX_FMT_YUV444P9LE]  = { 1 , 1 },
      [PIX_FMT_YUV444P10BE] = { 1 , 1 },
      [PIX_FMT_YUV444P10LE] = { 1 , 1 },
 +    [PIX_FMT_GBR24P]      = { 1 , 0 },
+     [PIX_FMT_GBRP]        = { 1 , 0 },
+     [PIX_FMT_GBRP9LE]     = { 1 , 0 },
+     [PIX_FMT_GBRP9BE]     = { 1 , 0 },
+     [PIX_FMT_GBRP10LE]    = { 1 , 0 },
+     [PIX_FMT_GBRP10BE]    = { 1 , 0 },
+     [PIX_FMT_GBRP16LE]    = { 1 , 0 },
+     [PIX_FMT_GBRP16BE]    = { 1 , 0 },
  };
  
  int sws_isSupportedInput(enum PixelFormat pix_fmt)
@@@ -161,12 -160,13 +168,12 @@@ int sws_isSupportedOutput(enum PixelFor
  
  extern const int32_t ff_yuv2rgb_coeffs[8][4];
  
 +#if FF_API_SWS_FORMAT_NAME
  const char *sws_format_name(enum PixelFormat format)
  {
 -    if ((unsigned)format < PIX_FMT_NB && av_pix_fmt_descriptors[format].name)
 -        return av_pix_fmt_descriptors[format].name;
 -    else
 -        return "Unknown format";
 +    return av_get_pix_fmt_name(format);
  }
 +#endif
  
  static double getSplineCoeff(double a, double b, double c, double d, double dist)
  {
@@@ -715,7 -715,7 +722,7 @@@ int sws_getColorspaceDetails(struct Sws
                               int *srcRange, int **table, int *dstRange,
                               int *brightness, int *contrast, int *saturation)
  {
 -    if (isYUV(c->dstFormat) || isGray(c->dstFormat)) return -1;
 +    if (!c || isYUV(c->dstFormat) || isGray(c->dstFormat)) return -1;
  
      *inv_table = c->srcColorspaceTable;
      *table     = c->dstColorspaceTable;
@@@ -751,7 -751,7 +758,7 @@@ SwsContext *sws_alloc_context(void
  
  int sws_init_context(SwsContext *c, SwsFilter *srcFilter, SwsFilter *dstFilter)
  {
 -    int i;
 +    int i, j;
      int usesVFilter, usesHFilter;
      int unscaled;
      SwsFilter dummyFilter= {NULL, NULL, NULL, NULL};
      int srcH= c->srcH;
      int dstW= c->dstW;
      int dstH= c->dstH;
 -    int dst_stride = FFALIGN(dstW * sizeof(int16_t) + 16, 16), dst_stride_px = dst_stride >> 1;
 +    int dst_stride = FFALIGN(dstW * sizeof(int16_t)+66, 16);
      int flags, cpu_flags;
      enum PixelFormat srcFormat= c->srcFormat;
      enum PixelFormat dstFormat= c->dstFormat;
  
      unscaled = (srcW == dstW && srcH == dstH);
  
 +    handle_jpeg(&srcFormat);
 +    handle_jpeg(&dstFormat);
 +
 +    if(srcFormat!=c->srcFormat || dstFormat!=c->dstFormat){
 +        av_log(c, AV_LOG_WARNING, "deprecated pixel format used, make sure you did set range correctly\n");
 +        c->srcFormat= srcFormat;
 +        c->dstFormat= dstFormat;
 +    }
 +
      if (!sws_isSupportedInput(srcFormat)) {
 -        av_log(c, AV_LOG_ERROR, "%s is not supported as input pixel format\n", sws_format_name(srcFormat));
 +        av_log(c, AV_LOG_ERROR, "%s is not supported as input pixel format\n", av_get_pix_fmt_name(srcFormat));
          return AVERROR(EINVAL);
      }
      if (!sws_isSupportedOutput(dstFormat)) {
 -        av_log(c, AV_LOG_ERROR, "%s is not supported as output pixel format\n", sws_format_name(dstFormat));
 +        av_log(c, AV_LOG_ERROR, "%s is not supported as output pixel format\n", av_get_pix_fmt_name(dstFormat));
          return AVERROR(EINVAL);
      }
  
      getSubSampleFactors(&c->chrDstHSubSample, &c->chrDstVSubSample, dstFormat);
  
      // reuse chroma for 2 pixels RGB/BGR unless user wants full chroma interpolation
 -    if (flags & SWS_FULL_CHR_H_INT &&
 -        dstFormat != PIX_FMT_RGBA &&
 -        dstFormat != PIX_FMT_ARGB &&
 -        dstFormat != PIX_FMT_BGRA &&
 -        dstFormat != PIX_FMT_ABGR &&
 -        dstFormat != PIX_FMT_RGB24 &&
 -        dstFormat != PIX_FMT_BGR24) {
 -        av_log(c, AV_LOG_ERROR,
 -               "full chroma interpolation for destination format '%s' not yet implemented\n",
 -               sws_format_name(dstFormat));
 -        flags &= ~SWS_FULL_CHR_H_INT;
 -        c->flags = flags;
 -    }
      if (isAnyRGB(dstFormat) && !(flags&SWS_FULL_CHR_H_INT)) c->chrDstHSubSample=1;
  
      // drop some chroma lines if the user wants it
          if (c->swScale) {
              if (flags&SWS_PRINT_INFO)
                  av_log(c, AV_LOG_INFO, "using unscaled %s -> %s special converter\n",
 -                       sws_format_name(srcFormat), sws_format_name(dstFormat));
 +                       av_get_pix_fmt_name(srcFormat), av_get_pix_fmt_name(dstFormat));
              return 0;
          }
      }
      c->dstBpc = 1 + av_pix_fmt_descriptors[dstFormat].comp[0].depth_minus1;
      if (c->dstBpc < 8)
          c->dstBpc = 8;
 +    if (isAnyRGB(srcFormat) || srcFormat == PIX_FMT_PAL8)
 +        c->srcBpc = 16;
      if (c->dstBpc == 16)
          dst_stride <<= 1;
 -    FF_ALLOC_OR_GOTO(c, c->formatConvBuffer,
 -                     (FFALIGN(srcW, 16) * 2 * FFALIGN(c->srcBpc, 8) >> 3) + 16,
 -                     fail);
 +    FF_ALLOC_OR_GOTO(c, c->formatConvBuffer, FFALIGN(srcW*2+78, 16) * 2, fail);
      if (HAVE_MMX2 && cpu_flags & AV_CPU_FLAG_MMX2 && c->srcBpc == 8 && c->dstBpc <= 10) {
          c->canMMX2BeUsed= (dstW >=srcW && (dstW&31)==0 && (srcW&15)==0) ? 1 : 0;
          if (!c->canMMX2BeUsed && dstW >=srcW && (srcW&15)==0 && (flags&SWS_FAST_BILINEAR)) {
              if (flags&SWS_PRINT_INFO)
                  av_log(c, AV_LOG_INFO, "output width is not a multiple of 32 -> no MMX2 scaler\n");
          }
 -        if (usesHFilter) c->canMMX2BeUsed=0;
 +        if (usesHFilter || isNBPS(c->srcFormat) || is16BPS(c->srcFormat) || isAnyRGB(c->srcFormat)) c->canMMX2BeUsed=0;
      }
      else
          c->canMMX2BeUsed=0;
              c->chrXInc+= 20;
          }
          //we don't use the x86 asm scaler if MMX is available
 -        else if (HAVE_MMX && cpu_flags & AV_CPU_FLAG_MMX) {
 +        else if (HAVE_MMX && cpu_flags & AV_CPU_FLAG_MMX && c->dstBpc <= 10) {
              c->lumXInc = ((srcW-2)<<16)/(dstW-2) - 20;
              c->chrXInc = ((c->chrSrcW-2)<<16)/(c->chrDstW-2) - 20;
          }
              c->chrMmx2FilterCode = av_malloc(c->chrMmx2FilterCodeSize);
  #endif
  
 +#ifdef MAP_ANONYMOUS
 +            if (c->lumMmx2FilterCode == MAP_FAILED || c->chrMmx2FilterCode == MAP_FAILED)
 +#else
              if (!c->lumMmx2FilterCode || !c->chrMmx2FilterCode)
 +#endif
                  return AVERROR(ENOMEM);
              FF_ALLOCZ_OR_GOTO(c, c->hLumFilter   , (dstW        /8+8)*sizeof(int16_t), fail);
              FF_ALLOCZ_OR_GOTO(c, c->hChrFilter   , (c->chrDstW  /4+8)*sizeof(int16_t), fail);
              FF_ALLOCZ_OR_GOTO(c, c->hLumFilterPos, (dstW      /2/8+8)*sizeof(int32_t), fail);
              FF_ALLOCZ_OR_GOTO(c, c->hChrFilterPos, (c->chrDstW/2/4+8)*sizeof(int32_t), fail);
  
 -            initMMX2HScaler(      dstW, c->lumXInc, c->lumMmx2FilterCode, c->hLumFilter, c->hLumFilterPos, 8);
 -            initMMX2HScaler(c->chrDstW, c->chrXInc, c->chrMmx2FilterCode, c->hChrFilter, c->hChrFilterPos, 4);
 +            initMMX2HScaler(      dstW, c->lumXInc, c->lumMmx2FilterCode, c->hLumFilter, (uint32_t*)c->hLumFilterPos, 8);
 +            initMMX2HScaler(c->chrDstW, c->chrXInc, c->chrMmx2FilterCode, c->hChrFilter, (uint32_t*)c->hChrFilterPos, 4);
  
  #ifdef MAP_ANONYMOUS
              mprotect(c->lumMmx2FilterCode, c->lumMmx2FilterCodeSize, PROT_EXEC | PROT_READ);
      c->vLumBufSize= c->vLumFilterSize;
      c->vChrBufSize= c->vChrFilterSize;
      for (i=0; i<dstH; i++) {
 -        int chrI= i*c->chrDstH / dstH;
 +        int chrI= (int64_t)i*c->chrDstH / dstH;
          int nextSlice= FFMAX(c->vLumFilterPos[i   ] + c->vLumFilterSize - 1,
                             ((c->vChrFilterPos[chrI] + c->vChrFilterSize - 1)<<c->chrSrcVSubSample));
  
          FF_ALLOCZ_OR_GOTO(c, c->lumPixBuf[i+c->vLumBufSize], dst_stride+16, fail);
          c->lumPixBuf[i] = c->lumPixBuf[i+c->vLumBufSize];
      }
 -    // 64 / (c->dstBpc & ~7) is the same as 16 / sizeof(scaling_intermediate)
 -    c->uv_off_px   = dst_stride_px + 64 / (c->dstBpc &~ 7);
 -    c->uv_off_byte = dst_stride + 16;
 +    // 64 / c->scalingBpp is the same as 16 / sizeof(scaling_intermediate)
 +    c->uv_off   = (dst_stride>>1) + 64 / (c->dstBpc &~ 7);
 +    c->uv_offx2 = dst_stride + 16;
      for (i=0; i<c->vChrBufSize; i++) {
          FF_ALLOC_OR_GOTO(c, c->chrUPixBuf[i+c->vChrBufSize], dst_stride*2+32, fail);
          c->chrUPixBuf[i] = c->chrUPixBuf[i+c->vChrBufSize];
  
      //try to avoid drawing green stuff between the right end and the stride end
      for (i=0; i<c->vChrBufSize; i++)
 -        memset(c->chrUPixBuf[i], 64, dst_stride*2+1);
 +        if(av_pix_fmt_descriptors[c->dstFormat].comp[0].depth_minus1 == 15){
 +            av_assert0(c->dstBpc > 10);
 +            for(j=0; j<dst_stride/2+1; j++)
 +                ((int32_t*)(c->chrUPixBuf[i]))[j] = 1<<18;
 +        } else
 +            for(j=0; j<dst_stride+1; j++)
 +                ((int16_t*)(c->chrUPixBuf[i]))[j] = 1<<14;
  
      assert(c->chrDstH <= dstH);
  
          else                              av_log(c, AV_LOG_INFO, "ehh flags invalid?! ");
  
          av_log(c, AV_LOG_INFO, "from %s to %s%s ",
 -               sws_format_name(srcFormat),
 +               av_get_pix_fmt_name(srcFormat),
  #ifdef DITHER1XBPP
                 dstFormat == PIX_FMT_BGR555 || dstFormat == PIX_FMT_BGR565 ||
                 dstFormat == PIX_FMT_RGB444BE || dstFormat == PIX_FMT_RGB444LE ||
  #else
                 "",
  #endif
 -               sws_format_name(dstFormat));
 +               av_get_pix_fmt_name(dstFormat));
  
          if      (HAVE_MMX2     && cpu_flags & AV_CPU_FLAG_MMX2)    av_log(c, AV_LOG_INFO, "using MMX2\n");
          else if (HAVE_AMD3DNOW && cpu_flags & AV_CPU_FLAG_3DNOW)   av_log(c, AV_LOG_INFO, "using 3DNOW\n");
@@@ -1483,7 -1477,7 +1490,7 @@@ void sws_freeContext(SwsContext *c
  #endif /* HAVE_MMX */
  
      av_freep(&c->yuvTable);
 -    av_free(c->formatConvBuffer);
 +    av_freep(&c->formatConvBuffer);
  
      av_free(c);
  }