Merge commit '88bd7fdc821aaa0cbcf44cf075c62aaa42121e3f'
authorMichael Niedermayer <michaelni@gmx.at>
Wed, 23 Jan 2013 16:44:56 +0000 (17:44 +0100)
committerMichael Niedermayer <michaelni@gmx.at>
Wed, 23 Jan 2013 16:44:56 +0000 (17:44 +0100)
* commit '88bd7fdc821aaa0cbcf44cf075c62aaa42121e3f':
  Drop DCTELEM typedef

Conflicts:
libavcodec/alpha/dsputil_alpha.h
libavcodec/alpha/motion_est_alpha.c
libavcodec/arm/dsputil_init_armv6.c
libavcodec/bfin/dsputil_bfin.h
libavcodec/bfin/pixels_bfin.S
libavcodec/cavs.c
libavcodec/cavsdec.c
libavcodec/dct-test.c
libavcodec/dnxhdenc.c
libavcodec/dsputil.c
libavcodec/dsputil.h
libavcodec/dsputil_template.c
libavcodec/eamad.c
libavcodec/h264_cavlc.c
libavcodec/h264idct_template.c
libavcodec/mpeg12.c
libavcodec/mpegvideo.c
libavcodec/mpegvideo.h
libavcodec/mpegvideo_enc.c
libavcodec/ppc/dsputil_altivec.c
libavcodec/proresdsp.c

Merged-by: Michael Niedermayer <michaelni@gmx.at>
157 files changed:
1  2 
doc/optimization.txt
libavcodec/4xm.c
libavcodec/alpha/dsputil_alpha.c
libavcodec/alpha/dsputil_alpha.h
libavcodec/alpha/dsputil_alpha_asm.S
libavcodec/alpha/motion_est_alpha.c
libavcodec/alpha/mpegvideo_alpha.c
libavcodec/alpha/simple_idct_alpha.c
libavcodec/arm/dsputil_init_arm.c
libavcodec/arm/dsputil_init_armv5te.c
libavcodec/arm/dsputil_init_armv6.c
libavcodec/arm/dsputil_init_neon.c
libavcodec/arm/h264dsp_init_arm.c
libavcodec/arm/mpegvideo_arm.c
libavcodec/arm/mpegvideo_armv5te.c
libavcodec/arm/rv34dsp_init_arm.c
libavcodec/arm/simple_idct_armv6.S
libavcodec/arm/simple_idct_neon.S
libavcodec/arm/vp3dsp_init_arm.c
libavcodec/arm/vp8.h
libavcodec/asv.h
libavcodec/asvdec.c
libavcodec/asvenc.c
libavcodec/bfin/config_bfin.h
libavcodec/bfin/dsputil_bfin.c
libavcodec/bfin/dsputil_bfin.h
libavcodec/bfin/fdct_bfin.S
libavcodec/bfin/idct_bfin.S
libavcodec/bfin/mpegvideo_bfin.c
libavcodec/bfin/pixels_bfin.S
libavcodec/bfin/vp3_bfin.c
libavcodec/bfin/vp3_idct_bfin.S
libavcodec/bink.c
libavcodec/cavs.c
libavcodec/cavs.h
libavcodec/cavsdec.c
libavcodec/cavsdsp.c
libavcodec/cavsdsp.h
libavcodec/dct-test.c
libavcodec/dnxhddec.c
libavcodec/dnxhdenc.c
libavcodec/dnxhdenc.h
libavcodec/dsputil.c
libavcodec/dsputil.h
libavcodec/dsputil_template.c
libavcodec/dv.c
libavcodec/dvdata.h
libavcodec/dvdec.c
libavcodec/eaidct.c
libavcodec/eaidct.h
libavcodec/eamad.c
libavcodec/eatgq.c
libavcodec/eatqi.c
libavcodec/faandct.h
libavcodec/faanidct.c
libavcodec/faanidct.h
libavcodec/h261dec.c
libavcodec/h261enc.c
libavcodec/h263.c
libavcodec/h263.h
libavcodec/h264.c
libavcodec/h264.h
libavcodec/h264_cabac.c
libavcodec/h264_cavlc.c
libavcodec/h264_mb_template.c
libavcodec/h264dsp.h
libavcodec/h264idct_template.c
libavcodec/h264pred.h
libavcodec/h264pred_template.c
libavcodec/ituh263dec.c
libavcodec/ituh263enc.c
libavcodec/jrevdct.c
libavcodec/mdec.c
libavcodec/mimic.c
libavcodec/mjpegdec.c
libavcodec/mjpegdec.h
libavcodec/mjpegenc.c
libavcodec/mjpegenc.h
libavcodec/mpeg12.c
libavcodec/mpeg12.h
libavcodec/mpeg12enc.c
libavcodec/mpeg4video.h
libavcodec/mpeg4videodec.c
libavcodec/mpeg4videoenc.c
libavcodec/mpegvideo.c
libavcodec/mpegvideo.h
libavcodec/mpegvideo_enc.c
libavcodec/mpegvideo_xvmc.c
libavcodec/msmpeg4.c
libavcodec/msmpeg4.h
libavcodec/msmpeg4enc.c
libavcodec/ppc/dsputil_altivec.c
libavcodec/ppc/dsputil_ppc.c
libavcodec/ppc/h264_altivec.c
libavcodec/ppc/mpegvideo_altivec.c
libavcodec/ppc/vc1dsp_altivec.c
libavcodec/ppc/vp3dsp_altivec.c
libavcodec/proresdec2.c
libavcodec/proresdec_lgpl.c
libavcodec/proresdsp.c
libavcodec/proresdsp.h
libavcodec/proresenc_anatoliy.c
libavcodec/proresenc_kostya.c
libavcodec/rtjpeg.c
libavcodec/rtjpeg.h
libavcodec/rv34.c
libavcodec/sh4/dsputil_sh4.c
libavcodec/sh4/dsputil_sh4.h
libavcodec/sh4/idct_sh4.c
libavcodec/simple_idct.c
libavcodec/simple_idct.h
libavcodec/simple_idct_template.c
libavcodec/sparc/dsputil_vis.h
libavcodec/sparc/simple_idct_vis.c
libavcodec/svq3.c
libavcodec/vc1.h
libavcodec/vc1dec.c
libavcodec/vc1dsp.c
libavcodec/vc1dsp.h
libavcodec/vp3.c
libavcodec/vp3dsp.c
libavcodec/vp3dsp.h
libavcodec/vp56.h
libavcodec/vp8.c
libavcodec/vp8.h
libavcodec/vp8dsp.c
libavcodec/vp8dsp.h
libavcodec/wmv2.c
libavcodec/wmv2.h
libavcodec/wmv2dec.c
libavcodec/wmv2dsp.c
libavcodec/wmv2dsp.h
libavcodec/wmv2enc.c
libavcodec/x86/dnxhdenc.c
libavcodec/x86/dsputil_mmx.c
libavcodec/x86/dsputil_mmx.h
libavcodec/x86/dsputilenc.asm
libavcodec/x86/dsputilenc_mmx.c
libavcodec/x86/h264_idct.asm
libavcodec/x86/h264_intrapred_init.c
libavcodec/x86/h264dsp_init.c
libavcodec/x86/idct_mmx_xvid.c
libavcodec/x86/idct_xvid.h
libavcodec/x86/mpegvideo.c
libavcodec/x86/mpegvideoenc_template.c
libavcodec/x86/proresdsp.asm
libavcodec/x86/proresdsp_init.c
libavcodec/x86/simple_idct.c
libavcodec/x86/vc1dsp_mmx.c
libavcodec/x86/vp3dsp_init.c
libavcodec/x86/vp8dsp.asm
libavcodec/x86/vp8dsp_init.c
libavfilter/libmpcodecs/vf_fspp.c
libavfilter/libmpcodecs/vf_pp7.c
libavfilter/libmpcodecs/vf_spp.c
libavfilter/vf_decimate.c
tools/patcheck

Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -518,7 -518,7 +518,7 @@@ DEFUN_END(pix_sum
  
  
  DEFUN(get_pixels,mL1,
-         (DCTELEM *av_restrict block, const uint8_t *pixels, int line_size)):
 -        (int16_t *restrict block, const uint8_t *pixels, int line_size)):
++        (int16_t *av_restrict block, const uint8_t *pixels, int line_size)):
          [--sp] = (r7:4);
          i3=r0;        // dest
          i0=r1;        // src0
Simple merge
Simple merge
Simple merge
@@@ -704,18 -702,18 +704,18 @@@ int ff_cavs_init_pic(AVSContext *h) 
   */
  void ff_cavs_init_top_lines(AVSContext *h) {
      /* alloc top line of predictors */
 -    h->top_qp       = av_malloc( h->mb_width);
 -    h->top_mv[0]    = av_malloc((h->mb_width*2+1)*sizeof(cavs_vector));
 -    h->top_mv[1]    = av_malloc((h->mb_width*2+1)*sizeof(cavs_vector));
 -    h->top_pred_Y   = av_malloc( h->mb_width*2*sizeof(*h->top_pred_Y));
 -    h->top_border_y = av_malloc((h->mb_width+1)*16);
 -    h->top_border_u = av_malloc( h->mb_width * 10);
 -    h->top_border_v = av_malloc( h->mb_width * 10);
 +    h->top_qp       = av_mallocz( h->mb_width);
 +    h->top_mv[0]    = av_mallocz((h->mb_width*2+1)*sizeof(cavs_vector));
 +    h->top_mv[1]    = av_mallocz((h->mb_width*2+1)*sizeof(cavs_vector));
 +    h->top_pred_Y   = av_mallocz( h->mb_width*2*sizeof(*h->top_pred_Y));
 +    h->top_border_y = av_mallocz((h->mb_width+1)*16);
 +    h->top_border_u = av_mallocz( h->mb_width * 10);
 +    h->top_border_v = av_mallocz( h->mb_width * 10);
  
      /* alloc space for co-located MVs and types */
 -    h->col_mv       = av_malloc( h->mb_width*h->mb_height*4*sizeof(cavs_vector));
 -    h->col_type_base = av_malloc(h->mb_width*h->mb_height);
 +    h->col_mv       = av_mallocz( h->mb_width*h->mb_height*4*sizeof(cavs_vector));
 +    h->col_type_base = av_mallocz(h->mb_width*h->mb_height);
-     h->block        = av_mallocz(64*sizeof(DCTELEM));
+     h->block        = av_mallocz(64*sizeof(int16_t));
  }
  
  av_cold int ff_cavs_init(AVCodecContext *avctx) {
Simple merge
@@@ -551,13 -550,12 +551,13 @@@ static int decode_residual_block(AVSCon
                                   const struct dec_2dvlc *r, int esc_golomb_order,
                                   int qp, uint8_t *dst, int stride)
  {
 -    int i, level_code, esc_code, level, run, mask;
 +    int i, esc_code, level, mask;
 +    unsigned int level_code, run;
-     DCTELEM level_buf[65];
+     int16_t level_buf[65];
      uint8_t run_buf[65];
-     DCTELEM *block = h->block;
+     int16_t *block = h->block;
  
 -    for (i = 0;i < 65; i++) {
 +    for (i = 0; i < 65; i++) {
          level_code = get_ue_code(gb, r->golomb_order);
          if (level_code >= ESCAPE_CODE) {
              run      = ((level_code - ESCAPE_CODE) >> 1) + 1;
Simple merge
Simple merge
  
  #undef printf
  
- void ff_mmx_idct(DCTELEM *data);
- void ff_mmxext_idct(DCTELEM *data);
++void ff_mmx_idct(int16_t *data);
++void ff_mmxext_idct(int16_t *data);
 +
  // BFIN
- void ff_bfin_idct(DCTELEM *block);
- void ff_bfin_fdct(DCTELEM *block);
+ void ff_bfin_idct(int16_t *block);
+ void ff_bfin_fdct(int16_t *block);
  
  // ALTIVEC
- void ff_fdct_altivec(DCTELEM *block);
+ void ff_fdct_altivec(int16_t *block);
  
  // ARM
- void ff_j_rev_dct_arm(DCTELEM *data);
- void ff_simple_idct_arm(DCTELEM *data);
- void ff_simple_idct_armv5te(DCTELEM *data);
- void ff_simple_idct_armv6(DCTELEM *data);
- void ff_simple_idct_neon(DCTELEM *data);
+ void ff_j_rev_dct_arm(int16_t *data);
+ void ff_simple_idct_arm(int16_t *data);
+ void ff_simple_idct_armv5te(int16_t *data);
+ void ff_simple_idct_armv6(int16_t *data);
+ void ff_simple_idct_neon(int16_t *data);
  
- void ff_simple_idct_axp(DCTELEM *data);
+ void ff_simple_idct_axp(int16_t *data);
  
  struct algo {
      const char *name;
-     void (*func)(DCTELEM *block);
+     void (*func)(int16_t *block);
      enum formattag { NO_PERM, MMX_PERM, MMX_SIMPLE_PERM, SCALE_PERM,
 -                     SSE2_PERM, PARTTRANS_PERM } format;
 +                     SSE2_PERM, PARTTRANS_PERM, TRANSPOSE_PERM } format;
      int mm_support;
      int nonspec;
  };
@@@ -101,23 -99,6 +102,23 @@@ static const struct algo fdct_tab[] = 
      { 0 }
  };
  
-                                 DCTELEM *block, int16_t *qmat);
 +#if ARCH_X86_64 && HAVE_MMX && HAVE_YASM
 +void ff_prores_idct_put_10_sse2(uint16_t *dst, int linesize,
- static void ff_prores_idct_put_10_sse2_wrap(DCTELEM *dst){
++                                int16_t *block, int16_t *qmat);
 +
++static void ff_prores_idct_put_10_sse2_wrap(int16_t *dst){
 +    DECLARE_ALIGNED(16, static int16_t, qmat)[64];
 +    DECLARE_ALIGNED(16, static int16_t, tmp)[64];
 +    int i;
 +
 +    for(i=0; i<64; i++){
 +        qmat[i]=4;
 +        tmp[i]= dst[i];
 +    }
 +    ff_prores_idct_put_10_sse2(dst, 16, tmp, qmat);
 +}
 +#endif
 +
  static const struct algo idct_tab[] = {
      { "FAANI",          ff_faanidct,           NO_PERM  },
      { "REF-DBL",        ff_ref_idct,           NO_PERM  },
@@@ -193,10 -167,10 +194,10 @@@ static void idct_mmx_init(void
      }
  }
  
- DECLARE_ALIGNED(16, static DCTELEM, block)[64];
- DECLARE_ALIGNED(8,  static DCTELEM, block1)[64];
+ DECLARE_ALIGNED(16, static int16_t, block)[64];
+ DECLARE_ALIGNED(8,  static int16_t, block1)[64];
  
- static void init_block(DCTELEM block[64], int test, int is_idct, AVLFG *prng, int vals)
 -static void init_block(int16_t block[64], int test, int is_idct, AVLFG *prng)
++static void init_block(int16_t block[64], int test, int is_idct, AVLFG *prng, int vals)
  {
      int i, j;
  
@@@ -251,9 -220,9 +252,9 @@@ static void permute(int16_t dst[64], co
      }
  }
  
 -static int dct_error(const struct algo *dct, int test, int is_idct, int speed)
 +static int dct_error(const struct algo *dct, int test, int is_idct, int speed, const int bits)
  {
-     void (*ref)(DCTELEM *block) = is_idct ? ff_ref_idct : ff_ref_fdct;
+     void (*ref)(int16_t *block) = is_idct ? ff_ref_idct : ff_ref_fdct;
      int it, i, scale;
      int err_inf, v;
      int64_t err2, ti, ti1, it1, err_sum = 0;
@@@ -49,11 -48,8 +49,11 @@@ typedef struct DNXHDContext 
      ScanTable scantable;
      const CIDEntry *cid_table;
      int bit_depth; // 8, 10 or 0 if not initialized at all.
-     void (*decode_dct_block)(struct DNXHDContext *ctx, DCTELEM *block,
+     void (*decode_dct_block)(struct DNXHDContext *ctx, int16_t *block,
                               int n, int qscale);
 +    int last_qscale;
 +    int luma_scale[64];
 +    int chroma_scale[64];
  } DNXHDContext;
  
  #define DNXHD_VLC_BITS 9
@@@ -51,7 -44,7 +51,7 @@@ static const AVClass class = 
  
  #define LAMBDA_FRAC_BITS 10
  
- static void dnxhd_8bit_get_pixels_8x4_sym(DCTELEM *av_restrict block, const uint8_t *pixels, int line_size)
 -static void dnxhd_8bit_get_pixels_8x4_sym(int16_t *restrict block, const uint8_t *pixels, int line_size)
++static void dnxhd_8bit_get_pixels_8x4_sym(int16_t *av_restrict block, const uint8_t *pixels, int line_size)
  {
      int i;
      for (i = 0; i < 4; i++) {
      memcpy(block + 24, block - 32, sizeof(*block) * 8);
  }
  
- static av_always_inline void dnxhd_10bit_get_pixels_8x4_sym(DCTELEM *av_restrict block, const uint8_t *pixels, int line_size)
 -static av_always_inline void dnxhd_10bit_get_pixels_8x4_sym(int16_t *restrict block, const uint8_t *pixels, int line_size)
++static av_always_inline void dnxhd_10bit_get_pixels_8x4_sym(int16_t *av_restrict block, const uint8_t *pixels, int line_size)
  {
      int i;
 -
 -    block += 32;
 +    const uint16_t* pixels16 = (const uint16_t*)pixels;
 +    line_size >>= 1;
  
      for (i = 0; i < 4; i++) {
 -        memcpy(block + i     * 8, pixels + i * line_size, 8 * sizeof(*block));
 -        memcpy(block - (i+1) * 8, pixels + i * line_size, 8 * sizeof(*block));
 +        block[0] = pixels16[0]; block[1] = pixels16[1];
 +        block[2] = pixels16[2]; block[3] = pixels16[3];
 +        block[4] = pixels16[4]; block[5] = pixels16[5];
 +        block[6] = pixels16[6]; block[7] = pixels16[7];
 +        pixels16 += line_size;
 +        block += 8;
      }
 +    memcpy(block,      block -  8, sizeof(*block) * 8);
 +    memcpy(block +  8, block - 16, sizeof(*block) * 8);
 +    memcpy(block + 16, block - 24, sizeof(*block) * 8);
 +    memcpy(block + 24, block - 32, sizeof(*block) * 8);
  }
  
- static int dnxhd_10bit_dct_quantize(MpegEncContext *ctx, DCTELEM *block,
+ static int dnxhd_10bit_dct_quantize(MpegEncContext *ctx, int16_t *block,
                                      int n, int qscale, int *overflow)
  {
      const uint8_t *scantable= ctx->intra_scantable.scantable;
@@@ -593,9 -578,10 +593,9 @@@ static int dnxhd_encode_thread(AVCodecC
          dnxhd_get_blocks(ctx, mb_x, mb_y);
  
          for (i = 0; i < 8; i++) {
-             DCTELEM *block = ctx->blocks[i];
+             int16_t *block = ctx->blocks[i];
              int overflow, n = dnxhd_switch_matrix(ctx, i);
 -            int last_index = ctx->m.dct_quantize(&ctx->m, block, i,
 -                                                 qscale, &overflow);
 +            int last_index = ctx->m.dct_quantize(&ctx->m, block, 4&(2*i), qscale, &overflow);
              //START_TIMER;
              dnxhd_encode_block(ctx, block, last_index, n);
              //STOP_TIMER("encode_block");
Simple merge
@@@ -351,7 -336,7 +351,7 @@@ static int sse16_c(void *v, uint8_t *pi
      return s;
  }
  
- static void diff_pixels_c(DCTELEM *av_restrict block, const uint8_t *s1,
 -static void diff_pixels_c(int16_t *restrict block, const uint8_t *s1,
++static void diff_pixels_c(int16_t *av_restrict block, const uint8_t *s1,
                            const uint8_t *s2, int stride){
      int i;
  
      }
  }
  
--
- static void put_pixels_clamped_c(const DCTELEM *block, uint8_t *av_restrict pixels,
 -static void put_pixels_clamped_c(const int16_t *block, uint8_t *restrict pixels,
++static void put_pixels_clamped_c(const int16_t *block, uint8_t *av_restrict pixels,
                                   int line_size)
  {
      int i;
      }
  }
  
- static void put_pixels_clamped4_c(const DCTELEM *block, uint8_t *av_restrict pixels,
++static void put_pixels_clamped4_c(const int16_t *block, uint8_t *av_restrict pixels,
 +                                 int line_size)
 +{
 +    int i;
 +
 +    /* read the pixels */
 +    for(i=0;i<4;i++) {
 +        pixels[0] = av_clip_uint8(block[0]);
 +        pixels[1] = av_clip_uint8(block[1]);
 +        pixels[2] = av_clip_uint8(block[2]);
 +        pixels[3] = av_clip_uint8(block[3]);
 +
 +        pixels += line_size;
 +        block += 8;
 +    }
 +}
 +
- static void put_pixels_clamped2_c(const DCTELEM *block, uint8_t *av_restrict pixels,
++static void put_pixels_clamped2_c(const int16_t *block, uint8_t *av_restrict pixels,
 +                                 int line_size)
 +{
 +    int i;
 +
 +    /* read the pixels */
 +    for(i=0;i<2;i++) {
 +        pixels[0] = av_clip_uint8(block[0]);
 +        pixels[1] = av_clip_uint8(block[1]);
 +
 +        pixels += line_size;
 +        block += 8;
 +    }
 +}
 +
- static void put_signed_pixels_clamped_c(const DCTELEM *block,
+ static void put_signed_pixels_clamped_c(const int16_t *block,
 -                                        uint8_t *restrict pixels,
 +                                        uint8_t *av_restrict pixels,
                                          int line_size)
  {
      int i, j;
      }
  }
  
- static void add_pixels_clamped_c(const DCTELEM *block, uint8_t *av_restrict pixels,
 -static void add_pixels_clamped_c(const int16_t *block, uint8_t *restrict pixels,
++static void add_pixels_clamped_c(const int16_t *block, uint8_t *av_restrict pixels,
                                   int line_size)
  {
      int i;
      }
  }
  
- static void add_pixels_clamped4_c(const DCTELEM *block, uint8_t *av_restrict pixels,
++static void add_pixels_clamped4_c(const int16_t *block, uint8_t *av_restrict pixels,
 +                          int line_size)
 +{
 +    int i;
 +
 +    /* read the pixels */
 +    for(i=0;i<4;i++) {
 +        pixels[0] = av_clip_uint8(pixels[0] + block[0]);
 +        pixels[1] = av_clip_uint8(pixels[1] + block[1]);
 +        pixels[2] = av_clip_uint8(pixels[2] + block[2]);
 +        pixels[3] = av_clip_uint8(pixels[3] + block[3]);
 +        pixels += line_size;
 +        block += 8;
 +    }
 +}
 +
- static void add_pixels_clamped2_c(const DCTELEM *block, uint8_t *av_restrict pixels,
++static void add_pixels_clamped2_c(const int16_t *block, uint8_t *av_restrict pixels,
 +                          int line_size)
 +{
 +    int i;
 +
 +    /* read the pixels */
 +    for(i=0;i<2;i++) {
 +        pixels[0] = av_clip_uint8(pixels[0] + block[0]);
 +        pixels[1] = av_clip_uint8(pixels[1] + block[1]);
 +        pixels += line_size;
 +        block += 8;
 +    }
 +}
 +
- static int sum_abs_dctelem_c(DCTELEM *block)
+ static int sum_abs_dctelem_c(int16_t *block)
  {
      int sum=0, i;
      for(i=0; i<64; i++)
@@@ -2160,9 -2030,9 +2159,9 @@@ static int hadamard8_intra8x8_c(/*MpegE
  
  static int dct_sad8x8_c(/*MpegEncContext*/ void *c, uint8_t *src1, uint8_t *src2, int stride, int h){
      MpegEncContext * const s= (MpegEncContext *)c;
-     LOCAL_ALIGNED_16(DCTELEM, temp, [64]);
+     LOCAL_ALIGNED_16(int16_t, temp, [64]);
  
 -    assert(h==8);
 +    av_assert2(h==8);
  
      s->dsp.diff_pixels(temp, src1, src2, stride);
      s->dsp.fdct(temp);
@@@ -2224,10 -2094,10 +2223,10 @@@ static int dct264_sad8x8_c(/*MpegEncCon
  
  static int dct_max8x8_c(/*MpegEncContext*/ void *c, uint8_t *src1, uint8_t *src2, int stride, int h){
      MpegEncContext * const s= (MpegEncContext *)c;
-     LOCAL_ALIGNED_16(DCTELEM, temp, [64]);
+     LOCAL_ALIGNED_16(int16_t, temp, [64]);
      int sum=0, i;
  
 -    assert(h==8);
 +    av_assert2(h==8);
  
      s->dsp.diff_pixels(temp, src1, src2, stride);
      s->dsp.fdct(temp);
  
  static int quant_psnr8x8_c(/*MpegEncContext*/ void *c, uint8_t *src1, uint8_t *src2, int stride, int h){
      MpegEncContext * const s= (MpegEncContext *)c;
-     LOCAL_ALIGNED_16(DCTELEM, temp, [64*2]);
-     DCTELEM * const bak = temp+64;
+     LOCAL_ALIGNED_16(int16_t, temp, [64*2]);
+     int16_t * const bak = temp+64;
      int sum=0, i;
  
 -    assert(h==8);
 +    av_assert2(h==8);
      s->mb_intra=0;
  
      s->dsp.diff_pixels(temp, src1, src2, stride);
@@@ -2588,37 -2458,6 +2587,37 @@@ static void ff_jref_idct_add(uint8_t *d
      add_pixels_clamped_c(block, dest, line_size);
  }
  
- static void ff_jref_idct4_put(uint8_t *dest, int line_size, DCTELEM *block)
++static void ff_jref_idct4_put(uint8_t *dest, int line_size, int16_t *block)
 +{
 +    ff_j_rev_dct4 (block);
 +    put_pixels_clamped4_c(block, dest, line_size);
 +}
- static void ff_jref_idct4_add(uint8_t *dest, int line_size, DCTELEM *block)
++static void ff_jref_idct4_add(uint8_t *dest, int line_size, int16_t *block)
 +{
 +    ff_j_rev_dct4 (block);
 +    add_pixels_clamped4_c(block, dest, line_size);
 +}
 +
- static void ff_jref_idct2_put(uint8_t *dest, int line_size, DCTELEM *block)
++static void ff_jref_idct2_put(uint8_t *dest, int line_size, int16_t *block)
 +{
 +    ff_j_rev_dct2 (block);
 +    put_pixels_clamped2_c(block, dest, line_size);
 +}
- static void ff_jref_idct2_add(uint8_t *dest, int line_size, DCTELEM *block)
++static void ff_jref_idct2_add(uint8_t *dest, int line_size, int16_t *block)
 +{
 +    ff_j_rev_dct2 (block);
 +    add_pixels_clamped2_c(block, dest, line_size);
 +}
 +
- static void ff_jref_idct1_put(uint8_t *dest, int line_size, DCTELEM *block)
++static void ff_jref_idct1_put(uint8_t *dest, int line_size, int16_t *block)
 +{
 +    dest[0] = av_clip_uint8((block[0] + 4)>>3);
 +}
- static void ff_jref_idct1_add(uint8_t *dest, int line_size, DCTELEM *block)
++static void ff_jref_idct1_add(uint8_t *dest, int line_size, int16_t *block)
 +{
 +    dest[0] = av_clip_uint8(dest[0] + ((block[0] + 4)>>3));
 +}
 +
  /* init static data */
  av_cold void ff_dsputil_static_init(void)
  {
  
  //#define DEBUG
  /* dct code */
- typedef short DCTELEM;
  
- void ff_fdct_ifast (DCTELEM *data);
- void ff_fdct_ifast248 (DCTELEM *data);
- void ff_jpeg_fdct_islow_8(DCTELEM *data);
- void ff_jpeg_fdct_islow_10(DCTELEM *data);
- void ff_fdct248_islow_8(DCTELEM *data);
- void ff_fdct248_islow_10(DCTELEM *data);
+ void ff_fdct_ifast(int16_t *data);
+ void ff_fdct_ifast248(int16_t *data);
+ void ff_jpeg_fdct_islow_8(int16_t *data);
+ void ff_jpeg_fdct_islow_10(int16_t *data);
+ void ff_fdct248_islow_8(int16_t *data);
+ void ff_fdct248_islow_10(int16_t *data);
  
- void ff_j_rev_dct (DCTELEM *data);
- void ff_j_rev_dct4 (DCTELEM *data);
- void ff_j_rev_dct2 (DCTELEM *data);
- void ff_j_rev_dct1 (DCTELEM *data);
+ void ff_j_rev_dct(int16_t *data);
++void ff_j_rev_dct4(int16_t *data);
++void ff_j_rev_dct2(int16_t *data);
++void ff_j_rev_dct1(int16_t *data);
  
- void ff_fdct_mmx(DCTELEM *block);
- void ff_fdct_mmxext(DCTELEM *block);
- void ff_fdct_sse2(DCTELEM *block);
+ void ff_fdct_mmx(int16_t *block);
+ void ff_fdct_mmxext(int16_t *block);
+ void ff_fdct_sse2(int16_t *block);
  
  #define H264_IDCT(depth) \
- void ff_h264_idct8_add_ ## depth ## _c(uint8_t *dst, DCTELEM *block, int stride);\
- void ff_h264_idct_add_ ## depth ## _c(uint8_t *dst, DCTELEM *block, int stride);\
- void ff_h264_idct8_dc_add_ ## depth ## _c(uint8_t *dst, DCTELEM *block, int stride);\
- void ff_h264_idct_dc_add_ ## depth ## _c(uint8_t *dst, DCTELEM *block, int stride);\
- void ff_h264_idct_add16_ ## depth ## _c(uint8_t *dst, const int *blockoffset, DCTELEM *block, int stride, const uint8_t nnzc[6*8]);\
- void ff_h264_idct_add16intra_ ## depth ## _c(uint8_t *dst, const int *blockoffset, DCTELEM *block, int stride, const uint8_t nnzc[6*8]);\
- void ff_h264_idct8_add4_ ## depth ## _c(uint8_t *dst, const int *blockoffset, DCTELEM *block, int stride, const uint8_t nnzc[6*8]);\
- void ff_h264_idct_add8_422_ ## depth ## _c(uint8_t **dest, const int *blockoffset, DCTELEM *block, int stride, const uint8_t nnzc[6*8]);\
- void ff_h264_idct_add8_ ## depth ## _c(uint8_t **dest, const int *blockoffset, DCTELEM *block, int stride, const uint8_t nnzc[6*8]);\
- void ff_h264_luma_dc_dequant_idct_ ## depth ## _c(DCTELEM *output, DCTELEM *input, int qmul);\
- void ff_h264_chroma422_dc_dequant_idct_ ## depth ## _c(DCTELEM *block, int qmul);\
- void ff_h264_chroma_dc_dequant_idct_ ## depth ## _c(DCTELEM *block, int qmul);
+ void ff_h264_idct8_add_ ## depth ## _c(uint8_t *dst, int16_t *block, int stride);\
+ void ff_h264_idct_add_ ## depth ## _c(uint8_t *dst, int16_t *block, int stride);\
+ void ff_h264_idct8_dc_add_ ## depth ## _c(uint8_t *dst, int16_t *block, int stride);\
+ void ff_h264_idct_dc_add_ ## depth ## _c(uint8_t *dst, int16_t *block, int stride);\
+ void ff_h264_idct_add16_ ## depth ## _c(uint8_t *dst, const int *blockoffset, int16_t *block, int stride, const uint8_t nnzc[6*8]);\
+ void ff_h264_idct_add16intra_ ## depth ## _c(uint8_t *dst, const int *blockoffset, int16_t *block, int stride, const uint8_t nnzc[6*8]);\
+ void ff_h264_idct8_add4_ ## depth ## _c(uint8_t *dst, const int *blockoffset, int16_t *block, int stride, const uint8_t nnzc[6*8]);\
+ void ff_h264_idct_add8_422_ ## depth ## _c(uint8_t **dest, const int *blockoffset, int16_t *block, int stride, const uint8_t nnzc[6*8]);\
+ void ff_h264_idct_add8_ ## depth ## _c(uint8_t **dest, const int *blockoffset, int16_t *block, int stride, const uint8_t nnzc[6*8]);\
+ void ff_h264_luma_dc_dequant_idct_ ## depth ## _c(int16_t *output, int16_t *input, int qmul);\
+ void ff_h264_chroma422_dc_dequant_idct_ ## depth ## _c(int16_t *block, int qmul);\
+ void ff_h264_chroma_dc_dequant_idct_ ## depth ## _c(int16_t *block, int qmul);
  
  H264_IDCT( 8)
  H264_IDCT( 9)
  H264_IDCT(10)
 +H264_IDCT(12)
 +H264_IDCT(14)
  
- void ff_svq3_luma_dc_dequant_idct_c(DCTELEM *output, DCTELEM *input, int qp);
- void ff_svq3_add_idct_c(uint8_t *dst, DCTELEM *block, int stride, int qp, int dc);
+ void ff_svq3_luma_dc_dequant_idct_c(int16_t *output, int16_t *input, int qp);
+ void ff_svq3_add_idct_c(uint8_t *dst, int16_t *block, int stride, int qp, int dc);
  
  /* encoding scans */
  extern const uint8_t ff_alternate_horizontal_scan[64];
@@@ -114,7 -114,7 +114,7 @@@ static void FUNCC(draw_edges)(uint8_t *
  }
  
  #define DCTELEM_FUNCS(dctcoef, suffix)                                  \
- static void FUNCC(get_pixels ## suffix)(DCTELEM *av_restrict _block,    \
 -static void FUNCC(get_pixels ## suffix)(int16_t *restrict _block,       \
++static void FUNCC(get_pixels ## suffix)(int16_t *av_restrict _block,    \
                                          const uint8_t *_pixels,         \
                                          int line_size)                  \
  {                                                                       \
      }                                                                   \
  }                                                                       \
                                                                          \
 -static void FUNCC(add_pixels8 ## suffix)(uint8_t *restrict _pixels,     \
 +static void FUNCC(add_pixels8 ## suffix)(uint8_t *av_restrict _pixels,  \
-                                          DCTELEM *_block,               \
+                                          int16_t *_block,               \
                                           int line_size)                 \
  {                                                                       \
      int i;                                                              \
      }                                                                   \
  }                                                                       \
                                                                          \
 -static void FUNCC(add_pixels4 ## suffix)(uint8_t *restrict _pixels,     \
 +static void FUNCC(add_pixels4 ## suffix)(uint8_t *av_restrict _pixels,  \
-                                          DCTELEM *_block,               \
+                                          int16_t *_block,               \
                                           int line_size)                 \
  {                                                                       \
      int i;                                                              \
diff --cc libavcodec/dv.c
Simple merge
Simple merge
@@@ -143,14 -142,14 +143,14 @@@ static int dv_decode_video_segment(AVCo
      PutBitContext pb, vs_pb;
      GetBitContext gb;
      BlockInfo mb_data[5 * DV_MAX_BPM], *mb, *mb1;
-     LOCAL_ALIGNED_16(DCTELEM, sblock, [5*DV_MAX_BPM], [64]);
+     LOCAL_ALIGNED_16(int16_t, sblock, [5*DV_MAX_BPM], [64]);
      LOCAL_ALIGNED_16(uint8_t, mb_bit_buffer, [  80 + FF_INPUT_BUFFER_PADDING_SIZE]); /* allow some slack */
      LOCAL_ALIGNED_16(uint8_t, vs_bit_buffer, [5*80 + FF_INPUT_BUFFER_PADDING_SIZE]); /* allow some slack */
 -    const int log2_blocksize = 3;
 +    const int log2_blocksize = 3-s->avctx->lowres;
      int is_field_mode[5];
  
 -    assert((((int)mb_bit_buffer) & 7) == 0);
 -    assert((((int)vs_bit_buffer) & 7) == 0);
 +    av_assert1((((int)mb_bit_buffer) & 7) == 0);
 +    av_assert1((((int)vs_bit_buffer) & 7) == 0);
  
      memset(sblock, 0, 5*DV_MAX_BPM*sizeof(*sblock));
  
Simple merge
Simple merge
@@@ -116,7 -110,7 +116,7 @@@ static inline void idct_put(MadContext 
      }
  }
  
- static inline int decode_block_intra(MadContext *s, DCTELEM * block)
 -static inline void decode_block_intra(MadContext *s, int16_t * block)
++static inline int decode_block_intra(MadContext *s, int16_t * block)
  {
      int level, i, j, run;
      RLTable *rl = &ff_rl_mpeg1;
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -1143,13 -1134,35 +1143,13 @@@ decode_intra_mb
              if(cbp&0x20){
                  for(chroma_idx=0; chroma_idx<2; chroma_idx++){
                      const uint32_t *qmul = h->dequant4_coeff[chroma_idx+1+(IS_INTRA( mb_type ) ? 0:3)][h->chroma_qp[chroma_idx]];
-                     DCTELEM *mb = h->mb + (16*(16 + 16*chroma_idx) << pixel_shift);
+                     int16_t *mb = h->mb + (16*(16 + 16*chroma_idx) << pixel_shift);
 -                    for (i8x8 = 0; i8x8 < 2; i8x8++) {
 -                        for (i4x4 = 0; i4x4 < 4; i4x4++) {
 -                            const int index = 16 + 16*chroma_idx + 8*i8x8 + i4x4;
 +                    for (i8x8=0; i8x8<num_c8x8; i8x8++) {
 +                        for (i4x4=0; i4x4<4; i4x4++) {
 +                            const int index= 16 + 16*chroma_idx + 8*i8x8 + i4x4;
                              if (decode_residual(h, gb, mb, index, scan + 1, qmul, 15) < 0)
                                  return -1;
 -                            mb += 16 << pixel_shift;
 -                        }
 -                    }
 -                }
 -            }else{
 -                fill_rectangle(&h->non_zero_count_cache[scan8[16]], 4, 4, 8, 0, 1);
 -                fill_rectangle(&h->non_zero_count_cache[scan8[32]], 4, 4, 8, 0, 1);
 -            }
 -        } else /* yuv420 */ {
 -            if(cbp&0x30){
 -                for(chroma_idx=0; chroma_idx<2; chroma_idx++)
 -                    if( decode_residual(h, gb, h->mb + ((256 + 16*16*chroma_idx) << pixel_shift), CHROMA_DC_BLOCK_INDEX+chroma_idx, chroma_dc_scan, NULL, 4) < 0){
 -                        return -1;
 -                    }
 -            }
 -
 -            if(cbp&0x20){
 -                for(chroma_idx=0; chroma_idx<2; chroma_idx++){
 -                    const uint32_t *qmul = h->dequant4_coeff[chroma_idx+1+(IS_INTRA( mb_type ) ? 0:3)][h->chroma_qp[chroma_idx]];
 -                    for(i4x4=0; i4x4<4; i4x4++){
 -                        const int index= 16 + 16*chroma_idx + i4x4;
 -                        if( decode_residual(h, gb, h->mb + (16*index << pixel_shift), index, scan + 1, qmul, 15) < 0){
 -                            return -1;
 +                            mb += 16<<pixel_shift;
                          }
                      }
                  }
Simple merge
Simple merge
@@@ -154,11 -154,11 +154,11 @@@ void FUNCC(ff_h264_idct8_add)(uint8_t *
  }
  
  // assumes all AC coefs are 0
- void FUNCC(ff_h264_idct_dc_add)(uint8_t *p_dst, DCTELEM *block, int stride){
+ void FUNCC(ff_h264_idct_dc_add)(uint8_t *_dst, int16_t *block, int stride){
      int i, j;
      int dc = (((dctcoef*)block)[0] + 32) >> 6;
-     pixel *dst = (pixel*)p_dst;
+     pixel *dst = (pixel*)_dst;
 -    stride /= sizeof(pixel);
 +    stride >>= sizeof(pixel)-1;
      for( j = 0; j < 4; j++ )
      {
          for( i = 0; i < 4; i++ )
      }
  }
  
- void FUNCC(ff_h264_idct8_dc_add)(uint8_t *p_dst, DCTELEM *block, int stride){
+ void FUNCC(ff_h264_idct8_dc_add)(uint8_t *_dst, int16_t *block, int stride){
      int i, j;
      int dc = (((dctcoef*)block)[0] + 32) >> 6;
-     pixel *dst = (pixel*)p_dst;
+     pixel *dst = (pixel*)_dst;
 -    stride /= sizeof(pixel);
 +    stride >>= sizeof(pixel)-1;
      for( j = 0; j < 8; j++ )
      {
          for( i = 0; i < 8; i++ )
Simple merge
Simple merge
@@@ -564,9 -563,8 +564,9 @@@ not_coded
  
  static int h263_skip_b_part(MpegEncContext *s, int cbp)
  {
-     LOCAL_ALIGNED_16(DCTELEM, dblock, [64]);
+     LOCAL_ALIGNED_16(int16_t, dblock, [64]);
      int i, mbi;
 +    int bli[6];
  
      /* we have to set s->mb_intra to zero to decode B-part of PB-frame correctly
       * but real value should be restored in order to be used later (in OBMC condition)
Simple merge
@@@ -940,216 -940,3 +940,216 @@@ void ff_j_rev_dct(DCTBLOCK data
      dataptr++;                  /* advance pointer to next column */
    }
  }
-   register DCTELEM *dataptr;
 +
 +#undef DCTSIZE
 +#define DCTSIZE 4
 +#define DCTSTRIDE 8
 +
 +void ff_j_rev_dct4(DCTBLOCK data)
 +{
 +  int32_t tmp0, tmp1, tmp2, tmp3;
 +  int32_t tmp10, tmp11, tmp12, tmp13;
 +  int32_t z1;
 +  int32_t d0, d2, d4, d6;
-           DCTELEM dcval = (DCTELEM) (d0 << PASS1_BITS);
++  register int16_t *dataptr;
 +  int rowctr;
 +
 +  /* Pass 1: process rows. */
 +  /* Note results are scaled up by sqrt(8) compared to a true IDCT; */
 +  /* furthermore, we scale the results by 2**PASS1_BITS. */
 +
 +  data[0] += 4;
 +
 +  dataptr = data;
 +
 +  for (rowctr = DCTSIZE-1; rowctr >= 0; rowctr--) {
 +    /* Due to quantization, we will usually find that many of the input
 +     * coefficients are zero, especially the AC terms.  We can exploit this
 +     * by short-circuiting the IDCT calculation for any row in which all
 +     * the AC terms are zero.  In that case each output is equal to the
 +     * DC coefficient (with scale factor as needed).
 +     * With typical images and quantization tables, half or more of the
 +     * row DCT calculations can be simplified this way.
 +     */
 +
 +    register int *idataptr = (int*)dataptr;
 +
 +    d0 = dataptr[0];
 +    d2 = dataptr[1];
 +    d4 = dataptr[2];
 +    d6 = dataptr[3];
 +
 +    if ((d2 | d4 | d6) == 0) {
 +      /* AC terms all zero */
 +      if (d0) {
 +          /* Compute a 32 bit value to assign. */
-     dataptr[0] = (DCTELEM) DESCALE(tmp10, CONST_BITS-PASS1_BITS);
-     dataptr[1] = (DCTELEM) DESCALE(tmp11, CONST_BITS-PASS1_BITS);
-     dataptr[2] = (DCTELEM) DESCALE(tmp12, CONST_BITS-PASS1_BITS);
-     dataptr[3] = (DCTELEM) DESCALE(tmp13, CONST_BITS-PASS1_BITS);
++          int16_t dcval = (int16_t) (d0 << PASS1_BITS);
 +          register int v = (dcval & 0xffff) | ((dcval << 16) & 0xffff0000);
 +
 +          idataptr[0] = v;
 +          idataptr[1] = v;
 +      }
 +
 +      dataptr += DCTSTRIDE;     /* advance pointer to next row */
 +      continue;
 +    }
 +
 +    /* Even part: reverse the even part of the forward DCT. */
 +    /* The rotator is sqrt(2)*c(-6). */
 +    if (d6) {
 +            if (d2) {
 +                    /* d0 != 0, d2 != 0, d4 != 0, d6 != 0 */
 +                    z1 = MULTIPLY(d2 + d6, FIX_0_541196100);
 +                    tmp2 = z1 + MULTIPLY(-d6, FIX_1_847759065);
 +                    tmp3 = z1 + MULTIPLY(d2, FIX_0_765366865);
 +
 +                    tmp0 = (d0 + d4) << CONST_BITS;
 +                    tmp1 = (d0 - d4) << CONST_BITS;
 +
 +                    tmp10 = tmp0 + tmp3;
 +                    tmp13 = tmp0 - tmp3;
 +                    tmp11 = tmp1 + tmp2;
 +                    tmp12 = tmp1 - tmp2;
 +            } else {
 +                    /* d0 != 0, d2 == 0, d4 != 0, d6 != 0 */
 +                    tmp2 = MULTIPLY(-d6, FIX_1_306562965);
 +                    tmp3 = MULTIPLY(d6, FIX_0_541196100);
 +
 +                    tmp0 = (d0 + d4) << CONST_BITS;
 +                    tmp1 = (d0 - d4) << CONST_BITS;
 +
 +                    tmp10 = tmp0 + tmp3;
 +                    tmp13 = tmp0 - tmp3;
 +                    tmp11 = tmp1 + tmp2;
 +                    tmp12 = tmp1 - tmp2;
 +            }
 +    } else {
 +            if (d2) {
 +                    /* d0 != 0, d2 != 0, d4 != 0, d6 == 0 */
 +                    tmp2 = MULTIPLY(d2, FIX_0_541196100);
 +                    tmp3 = MULTIPLY(d2, FIX_1_306562965);
 +
 +                    tmp0 = (d0 + d4) << CONST_BITS;
 +                    tmp1 = (d0 - d4) << CONST_BITS;
 +
 +                    tmp10 = tmp0 + tmp3;
 +                    tmp13 = tmp0 - tmp3;
 +                    tmp11 = tmp1 + tmp2;
 +                    tmp12 = tmp1 - tmp2;
 +            } else {
 +                    /* d0 != 0, d2 == 0, d4 != 0, d6 == 0 */
 +                    tmp10 = tmp13 = (d0 + d4) << CONST_BITS;
 +                    tmp11 = tmp12 = (d0 - d4) << CONST_BITS;
 +            }
 +      }
 +
 +    /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
 +
++    dataptr[0] = (int16_t) DESCALE(tmp10, CONST_BITS-PASS1_BITS);
++    dataptr[1] = (int16_t) DESCALE(tmp11, CONST_BITS-PASS1_BITS);
++    dataptr[2] = (int16_t) DESCALE(tmp12, CONST_BITS-PASS1_BITS);
++    dataptr[3] = (int16_t) DESCALE(tmp13, CONST_BITS-PASS1_BITS);
 +
 +    dataptr += DCTSTRIDE;       /* advance pointer to next row */
 +  }
 +
 +  /* Pass 2: process columns. */
 +  /* Note that we must descale the results by a factor of 8 == 2**3, */
 +  /* and also undo the PASS1_BITS scaling. */
 +
 +  dataptr = data;
 +  for (rowctr = DCTSIZE-1; rowctr >= 0; rowctr--) {
 +    /* Columns of zeroes can be exploited in the same way as we did with rows.
 +     * However, the row calculation has created many nonzero AC terms, so the
 +     * simplification applies less often (typically 5% to 10% of the time).
 +     * On machines with very fast multiplication, it's possible that the
 +     * test takes more time than it's worth.  In that case this section
 +     * may be commented out.
 +     */
 +
 +    d0 = dataptr[DCTSTRIDE*0];
 +    d2 = dataptr[DCTSTRIDE*1];
 +    d4 = dataptr[DCTSTRIDE*2];
 +    d6 = dataptr[DCTSTRIDE*3];
 +
 +    /* Even part: reverse the even part of the forward DCT. */
 +    /* The rotator is sqrt(2)*c(-6). */
 +    if (d6) {
 +            if (d2) {
 +                    /* d0 != 0, d2 != 0, d4 != 0, d6 != 0 */
 +                    z1 = MULTIPLY(d2 + d6, FIX_0_541196100);
 +                    tmp2 = z1 + MULTIPLY(-d6, FIX_1_847759065);
 +                    tmp3 = z1 + MULTIPLY(d2, FIX_0_765366865);
 +
 +                    tmp0 = (d0 + d4) << CONST_BITS;
 +                    tmp1 = (d0 - d4) << CONST_BITS;
 +
 +                    tmp10 = tmp0 + tmp3;
 +                    tmp13 = tmp0 - tmp3;
 +                    tmp11 = tmp1 + tmp2;
 +                    tmp12 = tmp1 - tmp2;
 +            } else {
 +                    /* d0 != 0, d2 == 0, d4 != 0, d6 != 0 */
 +                    tmp2 = MULTIPLY(-d6, FIX_1_306562965);
 +                    tmp3 = MULTIPLY(d6, FIX_0_541196100);
 +
 +                    tmp0 = (d0 + d4) << CONST_BITS;
 +                    tmp1 = (d0 - d4) << CONST_BITS;
 +
 +                    tmp10 = tmp0 + tmp3;
 +                    tmp13 = tmp0 - tmp3;
 +                    tmp11 = tmp1 + tmp2;
 +                    tmp12 = tmp1 - tmp2;
 +            }
 +    } else {
 +            if (d2) {
 +                    /* d0 != 0, d2 != 0, d4 != 0, d6 == 0 */
 +                    tmp2 = MULTIPLY(d2, FIX_0_541196100);
 +                    tmp3 = MULTIPLY(d2, FIX_1_306562965);
 +
 +                    tmp0 = (d0 + d4) << CONST_BITS;
 +                    tmp1 = (d0 - d4) << CONST_BITS;
 +
 +                    tmp10 = tmp0 + tmp3;
 +                    tmp13 = tmp0 - tmp3;
 +                    tmp11 = tmp1 + tmp2;
 +                    tmp12 = tmp1 - tmp2;
 +            } else {
 +                    /* d0 != 0, d2 == 0, d4 != 0, d6 == 0 */
 +                    tmp10 = tmp13 = (d0 + d4) << CONST_BITS;
 +                    tmp11 = tmp12 = (d0 - d4) << CONST_BITS;
 +            }
 +    }
 +
 +    /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
 +
 +    dataptr[DCTSTRIDE*0] = tmp10 >> (CONST_BITS+PASS1_BITS+3);
 +    dataptr[DCTSTRIDE*1] = tmp11 >> (CONST_BITS+PASS1_BITS+3);
 +    dataptr[DCTSTRIDE*2] = tmp12 >> (CONST_BITS+PASS1_BITS+3);
 +    dataptr[DCTSTRIDE*3] = tmp13 >> (CONST_BITS+PASS1_BITS+3);
 +
 +    dataptr++;                  /* advance pointer to next column */
 +  }
 +}
 +
 +void ff_j_rev_dct2(DCTBLOCK data){
 +  int d00, d01, d10, d11;
 +
 +  data[0] += 4;
 +  d00 = data[0+0*DCTSTRIDE] + data[1+0*DCTSTRIDE];
 +  d01 = data[0+0*DCTSTRIDE] - data[1+0*DCTSTRIDE];
 +  d10 = data[0+1*DCTSTRIDE] + data[1+1*DCTSTRIDE];
 +  d11 = data[0+1*DCTSTRIDE] - data[1+1*DCTSTRIDE];
 +
 +  data[0+0*DCTSTRIDE]= (d00 + d10)>>3;
 +  data[1+0*DCTSTRIDE]= (d01 + d11)>>3;
 +  data[0+1*DCTSTRIDE]= (d00 - d10)>>3;
 +  data[1+1*DCTSTRIDE]= (d01 - d11)>>3;
 +}
 +
 +void ff_j_rev_dct1(DCTBLOCK data){
 +  data[0] = (data[0] + 4)>>3;
 +}
 +
 +#undef FIX
 +#undef CONST_BITS
Simple merge
Simple merge
@@@ -1131,21 -947,23 +1131,21 @@@ static int mjpeg_decode_scan_progressiv
          last_scan = !~s->coefs_finished[c];
      }
  
 -    if (s->interlaced && s->bottom_field) {
 -        int offset      = linesize >> 1;
 -        data           += offset;
 -        reference_data += offset;
 -    }
 +    if (s->interlaced && s->bottom_field)
 +        data += linesize >> 1;
 +
 +    s->restart_count = 0;
  
      for (mb_y = 0; mb_y < s->mb_height; mb_y++) {
 -        int block_offset = mb_y * linesize * 8;
 -        uint8_t *ptr     = data + block_offset;
 +        uint8_t *ptr     = data + (mb_y * linesize * 8 >> s->avctx->lowres);
          int block_idx    = mb_y * s->block_stride[c];
-         DCTELEM (*block)[64] = &s->blocks[c][block_idx];
+         int16_t (*block)[64] = &s->blocks[c][block_idx];
          uint8_t *last_nnz    = &s->last_nnz[c][block_idx];
          for (mb_x = 0; mb_x < s->mb_width; mb_x++, block++, last_nnz++) {
 -            const int copy_mb = mb_bitmask && !get_bits1(&mb_bitmask_gb);
 -
 -            if (!copy_mb) {
                  int ret;
 +                if (s->restart_interval && !s->restart_count)
 +                    s->restart_count = s->restart_interval;
 +
                  if (Ah)
                      ret = decode_block_refinement(s, *block, last_nnz, s->ac_index[0],
                                                    quant_matrix, ss, se, Al, &EOBRUN);
Simple merge
@@@ -455,36 -427,18 +455,36 @@@ static void encode_block(MpegEncContex
          put_bits(&s->pb, huff_size_ac[0], huff_code_ac[0]);
  }
  
- void ff_mjpeg_encode_mb(MpegEncContext *s, DCTELEM block[6][64])
+ void ff_mjpeg_encode_mb(MpegEncContext *s, int16_t block[6][64])
  {
      int i;
 -    for(i=0;i<5;i++) {
 -        encode_block(s, block[i], i);
 -    }
 -    if (s->chroma_format == CHROMA_420) {
 +    if (s->chroma_format == CHROMA_444) {
 +        encode_block(s, block[0], 0);
 +        encode_block(s, block[2], 2);
 +        encode_block(s, block[4], 4);
 +        encode_block(s, block[8], 8);
          encode_block(s, block[5], 5);
 +        encode_block(s, block[9], 9);
 +
 +        if (16*s->mb_x+8 < s->width) {
 +            encode_block(s, block[1], 1);
 +            encode_block(s, block[3], 3);
 +            encode_block(s, block[6], 6);
 +            encode_block(s, block[10], 10);
 +            encode_block(s, block[7], 7);
 +            encode_block(s, block[11], 11);
 +        }
      } else {
 -        encode_block(s, block[6], 6);
 -        encode_block(s, block[5], 5);
 -        encode_block(s, block[7], 7);
 +        for(i=0;i<5;i++) {
 +            encode_block(s, block[i], i);
 +        }
 +        if (s->chroma_format == CHROMA_420) {
 +            encode_block(s, block[5], 5);
 +        } else {
 +            encode_block(s, block[6], 6);
 +            encode_block(s, block[5], 5);
 +            encode_block(s, block[7], 7);
 +        }
      }
  
      s->i_tex_bits += get_bits_diff(s);
@@@ -52,9 -53,9 +53,9 @@@ int  ff_mjpeg_encode_init(MpegEncContex
  void ff_mjpeg_encode_close(MpegEncContext *s);
  void ff_mjpeg_encode_picture_header(MpegEncContext *s);
  void ff_mjpeg_encode_picture_trailer(MpegEncContext *s);
 -void ff_mjpeg_encode_stuffing(PutBitContext *pbc);
 +void ff_mjpeg_encode_stuffing(MpegEncContext *s);
  void ff_mjpeg_encode_dc(MpegEncContext *s, int val,
                          uint8_t *huff_size, uint16_t *huff_code);
- void ff_mjpeg_encode_mb(MpegEncContext *s, DCTELEM block[6][64]);
+ void ff_mjpeg_encode_mb(MpegEncContext *s, int16_t block[6][64]);
  
  #endif /* AVCODEC_MJPEGENC_H */
@@@ -232,12 -231,7 +232,12 @@@ end
      return 0;
  }
  
- static inline int mpeg1_fast_decode_block_inter(MpegEncContext *s, DCTELEM *block, int n)
 +/**
 + * Note: this function can read out of range and crash for corrupt streams.
 + * Changing this would eat up any speed benefits it has.
 + * Do not use "fast" flag if you need the code to be robust.
 + */
+ static inline int mpeg1_fast_decode_block_inter(MpegEncContext *s, int16_t *block, int n)
  {
      int level, i, j, run;
      RLTable *rl = &ff_rl_mpeg1;
@@@ -388,13 -382,8 +388,13 @@@ end
      return 0;
  }
  
 +/**
 + * Note: this function can read out of range and crash for corrupt streams.
 + * Changing this would eat up any speed benefits it has.
 + * Do not use "fast" flag if you need the code to be robust.
 + */
  static inline int mpeg2_fast_decode_block_non_intra(MpegEncContext *s,
-                                                     DCTELEM *block, int n)
+                                                     int16_t *block, int n)
  {
      int level, i, j, run;
      RLTable *rl = &ff_rl_mpeg1;
@@@ -533,12 -522,7 +533,12 @@@ static inline int mpeg2_decode_block_in
      return 0;
  }
  
- static inline int mpeg2_fast_decode_block_intra(MpegEncContext *s, DCTELEM *block, int n)
 +/**
 + * Note: this function can read out of range and crash for corrupt streams.
 + * Changing this would eat up any speed benefits it has.
 + * Do not use "fast" flag if you need the code to be robust.
 + */
+ static inline int mpeg2_fast_decode_block_intra(MpegEncContext *s, int16_t *block, int n)
  {
      int level, dc, diff, j, run;
      int component;
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
  //#include <assert.h>
  
  static void dct_unquantize_mpeg1_intra_c(MpegEncContext *s,
-                                    DCTELEM *block, int n, int qscale);
+                                    int16_t *block, int n, int qscale);
  static void dct_unquantize_mpeg1_inter_c(MpegEncContext *s,
-                                    DCTELEM *block, int n, int qscale);
+                                    int16_t *block, int n, int qscale);
  static void dct_unquantize_mpeg2_intra_c(MpegEncContext *s,
-                                    DCTELEM *block, int n, int qscale);
+                                    int16_t *block, int n, int qscale);
  static void dct_unquantize_mpeg2_intra_bitexact(MpegEncContext *s,
-                                    DCTELEM *block, int n, int qscale);
+                                    int16_t *block, int n, int qscale);
  static void dct_unquantize_mpeg2_inter_c(MpegEncContext *s,
-                                    DCTELEM *block, int n, int qscale);
+                                    int16_t *block, int n, int qscale);
  static void dct_unquantize_h263_intra_c(MpegEncContext *s,
-                                   DCTELEM *block, int n, int qscale);
+                                   int16_t *block, int n, int qscale);
  static void dct_unquantize_h263_inter_c(MpegEncContext *s,
-                                   DCTELEM *block, int n, int qscale);
+                                   int16_t *block, int n, int qscale);
  
  
 -/* enable all paranoid tests for rounding, overflows, etc... */
 -//#define PARANOID
 -
  //#define DEBUG
  
  
@@@ -2503,8 -2136,8 +2503,8 @@@ void ff_clean_intra_table_entries(MpegE
     s->interlaced_dct : true if interlaced dct used (mpeg2)
   */
  static av_always_inline
- void MPV_decode_mb_internal(MpegEncContext *s, DCTELEM block[12][64],
+ void MPV_decode_mb_internal(MpegEncContext *s, int16_t block[12][64],
 -                            int is_mpeg12)
 +                            int lowres_flag, int is_mpeg12)
  {
      const int mb_xy = s->mb_y * s->mb_stride + s->mb_x;
      if(CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration){
@@@ -2746,15 -2367,13 +2746,15 @@@ skip_idct
      }
  }
  
- void ff_MPV_decode_mb(MpegEncContext *s, DCTELEM block[12][64]){
+ void ff_MPV_decode_mb(MpegEncContext *s, int16_t block[12][64]){
  #if !CONFIG_SMALL
      if(s->out_format == FMT_MPEG1) {
 -        MPV_decode_mb_internal(s, block, 1);
 +        if(s->avctx->lowres) MPV_decode_mb_internal(s, block, 1, 1);
 +        else                 MPV_decode_mb_internal(s, block, 0, 1);
      } else
  #endif
 -        MPV_decode_mb_internal(s, block, 0);
 +    if(s->avctx->lowres) MPV_decode_mb_internal(s, block, 1, 0);
 +    else                  MPV_decode_mb_internal(s, block, 0, 0);
  }
  
  /**
@@@ -676,16 -667,13 +676,16 @@@ typedef struct MpegEncContext 
      /* RTP specific */
      int rtp_mode;
  
 +    char *tc_opt_str;        ///< timecode option string
 +    AVTimecode tc;           ///< timecode context
 +
      uint8_t *ptr_lastgob;
      int swap_uv;             //vcr2 codec is an MPEG-2 variant with U and V swapped
-     DCTELEM (*pblocks[12])[64];
+     int16_t (*pblocks[12])[64];
  
-     DCTELEM (*block)[64]; ///< points to one of the following blocks
-     DCTELEM (*blocks)[12][64]; // for HQ mode we need to keep the best block
-     int (*decode_mb)(struct MpegEncContext *s, DCTELEM block[6][64]); // used by some codecs to avoid a switch()
+     int16_t (*block)[64]; ///< points to one of the following blocks
 -    int16_t (*blocks)[8][64]; // for HQ mode we need to keep the best block
++    int16_t (*blocks)[12][64]; // for HQ mode we need to keep the best block
+     int (*decode_mb)(struct MpegEncContext *s, int16_t block[6][64]); // used by some codecs to avoid a switch()
  #define SLICE_OK         0
  #define SLICE_ERROR     -1
  #define SLICE_END       -2 ///<end marker found
@@@ -809,10 -797,9 +809,10 @@@ void ff_er_frame_end(MpegEncContext *s)
  void ff_er_add_slice(MpegEncContext *s, int startx, int starty, int endx, int endy, int status);
  
  int ff_dct_common_init(MpegEncContext *s);
 +int ff_dct_encode_init(MpegEncContext *s);
  void ff_convert_matrix(DSPContext *dsp, int (*qmat)[64], uint16_t (*qmat16)[2][64],
                         const uint16_t *quant_matrix, int bias, int qmin, int qmax, int intra);
- int ff_dct_quantize_c(MpegEncContext *s, DCTELEM *block, int n, int qscale, int *overflow);
+ int ff_dct_quantize_c(MpegEncContext *s, int16_t *block, int n, int qscale, int *overflow);
  
  void ff_init_block_index(MpegEncContext *s);
  void ff_copy_picture(Picture *dst, Picture *src);
  //#include <assert.h>
  
  static int encode_picture(MpegEncContext *s, int picture_number);
- static int dct_quantize_refine(MpegEncContext *s, DCTELEM *block, int16_t *weight, DCTELEM *orig, int n, int qscale);
+ static int dct_quantize_refine(MpegEncContext *s, int16_t *block, int16_t *weight, int16_t *orig, int n, int qscale);
  static int sse_mb(MpegEncContext *s);
- static void denoise_dct_c(MpegEncContext *s, DCTELEM *block);
- static int dct_quantize_trellis_c(MpegEncContext *s, DCTELEM *block, int n, int qscale, int *overflow);
+ static void denoise_dct_c(MpegEncContext *s, int16_t *block);
+ static int dct_quantize_trellis_c(MpegEncContext *s, int16_t *block, int n, int qscale, int *overflow);
  
 -/* enable all paranoid tests for rounding, overflows, etc... */
 -//#define PARANOID
 -
  //#define DEBUG
  
  static uint8_t default_mv_penalty[MAX_FCODE + 1][MAX_MV * 2 + 1];
@@@ -1828,11 -1726,10 +1828,11 @@@ static void get_visual_weight(int16_t *
  static av_always_inline void encode_mb_internal(MpegEncContext *s,
                                                  int motion_x, int motion_y,
                                                  int mb_block_height,
 +                                                int mb_block_width,
                                                  int mb_block_count)
  {
 -    int16_t weight[8][64];
 -    int16_t orig[8][64];
 +    int16_t weight[12][64];
-     DCTELEM orig[12][64];
++    int16_t orig[12][64];
      const int mb_x = s->mb_x;
      const int mb_y = s->mb_y;
      int i;
              get_visual_weight(weight[5], ptr_cr                , wrap_c);
          if (!s->chroma_y_shift) { /* 422 */
              if (!skip_dct[6])
 -                get_visual_weight(weight[6], ptr_cb + (dct_offset >> 1),
 +                get_visual_weight(weight[6], ptr_cb + uv_dct_offset,
                                    wrap_c);
              if (!skip_dct[7])
 -                get_visual_weight(weight[7], ptr_cr + (dct_offset >> 1),
 +                get_visual_weight(weight[7], ptr_cr + uv_dct_offset,
                                    wrap_c);
          }
-         memcpy(orig[0], s->block[0], sizeof(DCTELEM) * 64 * mb_block_count);
+         memcpy(orig[0], s->block[0], sizeof(int16_t) * 64 * mb_block_count);
      }
  
      /* DCT & quantize */
Simple merge
@@@ -404,10 -406,9 +404,10 @@@ static int msmpeg4v2_decode_motion(Mpeg
      return val;
  }
  
- static int msmpeg4v12_decode_mb(MpegEncContext *s, DCTELEM block[6][64])
+ static int msmpeg4v12_decode_mb(MpegEncContext *s, int16_t block[6][64])
  {
      int cbp, code, i;
 +    uint32_t * const mb_type_ptr = &s->current_picture.f.mb_type[s->mb_x + s->mb_y*s->mb_stride];
  
      if (s->pict_type == AV_PICTURE_TYPE_P) {
          if (s->use_skip_mb_code) {
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 3b3175a,0000000..4634e70
mode 100644,000000..100644
--- /dev/null
@@@ -1,605 -1,0 +1,605 @@@
- static av_always_inline void decode_dc_coeffs(GetBitContext *gb, DCTELEM *out,
 +/*
 + * Copyright (c) 2010-2011 Maxim Poliakovski
 + * Copyright (c) 2010-2011 Elvis Presley
 + *
 + * This file is part of FFmpeg.
 + *
 + * FFmpeg is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU Lesser General Public
 + * License as published by the Free Software Foundation; either
 + * version 2.1 of the License, or (at your option) any later version.
 + *
 + * FFmpeg is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * Lesser General Public License for more details.
 + *
 + * You should have received a copy of the GNU Lesser General Public
 + * License along with FFmpeg; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
 +/**
 + * @file
 + * Known FOURCCs: 'apch' (HQ), 'apcn' (SD), 'apcs' (LT), 'acpo' (Proxy), 'ap4h' (4444)
 + */
 +
 +//#define DEBUG
 +
 +#define LONG_BITSTREAM_READER
 +
 +#include "avcodec.h"
 +#include "get_bits.h"
 +#include "internal.h"
 +#include "simple_idct.h"
 +#include "proresdec.h"
 +
 +static void permute(uint8_t *dst, const uint8_t *src, const uint8_t permutation[64])
 +{
 +    int i;
 +    for (i = 0; i < 64; i++)
 +        dst[i] = permutation[src[i]];
 +}
 +
 +static const uint8_t progressive_scan[64] = {
 +     0,  1,  8,  9,  2,  3, 10, 11,
 +    16, 17, 24, 25, 18, 19, 26, 27,
 +     4,  5, 12, 20, 13,  6,  7, 14,
 +    21, 28, 29, 22, 15, 23, 30, 31,
 +    32, 33, 40, 48, 41, 34, 35, 42,
 +    49, 56, 57, 50, 43, 36, 37, 44,
 +    51, 58, 59, 52, 45, 38, 39, 46,
 +    53, 60, 61, 54, 47, 55, 62, 63
 +};
 +
 +static const uint8_t interlaced_scan[64] = {
 +     0,  8,  1,  9, 16, 24, 17, 25,
 +     2, 10,  3, 11, 18, 26, 19, 27,
 +    32, 40, 33, 34, 41, 48, 56, 49,
 +    42, 35, 43, 50, 57, 58, 51, 59,
 +     4, 12,  5,  6, 13, 20, 28, 21,
 +    14,  7, 15, 22, 29, 36, 44, 37,
 +    30, 23, 31, 38, 45, 52, 60, 53,
 +    46, 39, 47, 54, 61, 62, 55, 63,
 +};
 +
 +static av_cold int decode_init(AVCodecContext *avctx)
 +{
 +    ProresContext *ctx = avctx->priv_data;
 +    uint8_t idct_permutation[64];
 +
 +    avctx->bits_per_raw_sample = 10;
 +
 +    ff_dsputil_init(&ctx->dsp, avctx);
 +    ff_proresdsp_init(&ctx->prodsp, avctx);
 +
 +    avctx->coded_frame = &ctx->frame;
 +    ctx->frame.type = AV_PICTURE_TYPE_I;
 +    ctx->frame.key_frame = 1;
 +
 +    ff_init_scantable_permutation(idct_permutation,
 +                                  ctx->prodsp.idct_permutation_type);
 +
 +    permute(ctx->progressive_scan, progressive_scan, idct_permutation);
 +    permute(ctx->interlaced_scan, interlaced_scan, idct_permutation);
 +
 +    return 0;
 +}
 +
 +static int decode_frame_header(ProresContext *ctx, const uint8_t *buf,
 +                               const int data_size, AVCodecContext *avctx)
 +{
 +    int hdr_size, width, height, flags;
 +    int version;
 +    const uint8_t *ptr;
 +
 +    hdr_size = AV_RB16(buf);
 +    av_dlog(avctx, "header size %d\n", hdr_size);
 +    if (hdr_size > data_size) {
 +        av_log(avctx, AV_LOG_ERROR, "error, wrong header size\n");
 +        return -1;
 +    }
 +
 +    version = AV_RB16(buf + 2);
 +    av_dlog(avctx, "%.4s version %d\n", buf+4, version);
 +    if (version > 1) {
 +        av_log(avctx, AV_LOG_ERROR, "unsupported version: %d\n", version);
 +        return -1;
 +    }
 +
 +    width  = AV_RB16(buf + 8);
 +    height = AV_RB16(buf + 10);
 +    if (width != avctx->width || height != avctx->height) {
 +        av_log(avctx, AV_LOG_ERROR, "picture resolution change: %dx%d -> %dx%d\n",
 +               avctx->width, avctx->height, width, height);
 +        return -1;
 +    }
 +
 +    ctx->frame_type = (buf[12] >> 2) & 3;
 +
 +    av_dlog(avctx, "frame type %d\n", ctx->frame_type);
 +
 +    if (ctx->frame_type == 0) {
 +        ctx->scan = ctx->progressive_scan; // permuted
 +    } else {
 +        ctx->scan = ctx->interlaced_scan; // permuted
 +        ctx->frame.interlaced_frame = 1;
 +        ctx->frame.top_field_first = ctx->frame_type == 1;
 +    }
 +
 +    avctx->pix_fmt = (buf[12] & 0xC0) == 0xC0 ? AV_PIX_FMT_YUV444P10 : AV_PIX_FMT_YUV422P10;
 +
 +    ptr   = buf + 20;
 +    flags = buf[19];
 +    av_dlog(avctx, "flags %x\n", flags);
 +
 +    if (flags & 2) {
 +        if(buf + data_size - ptr < 64) {
 +            av_log(avctx, AV_LOG_ERROR, "Header truncated\n");
 +            return -1;
 +        }
 +        permute(ctx->qmat_luma, ctx->prodsp.idct_permutation, ptr);
 +        ptr += 64;
 +    } else {
 +        memset(ctx->qmat_luma, 4, 64);
 +    }
 +
 +    if (flags & 1) {
 +        if(buf + data_size - ptr < 64) {
 +            av_log(avctx, AV_LOG_ERROR, "Header truncated\n");
 +            return -1;
 +        }
 +        permute(ctx->qmat_chroma, ctx->prodsp.idct_permutation, ptr);
 +    } else {
 +        memset(ctx->qmat_chroma, 4, 64);
 +    }
 +
 +    return hdr_size;
 +}
 +
 +static int decode_picture_header(AVCodecContext *avctx, const uint8_t *buf, const int buf_size)
 +{
 +    ProresContext *ctx = avctx->priv_data;
 +    int i, hdr_size, slice_count;
 +    unsigned pic_data_size;
 +    int log2_slice_mb_width, log2_slice_mb_height;
 +    int slice_mb_count, mb_x, mb_y;
 +    const uint8_t *data_ptr, *index_ptr;
 +
 +    hdr_size = buf[0] >> 3;
 +    if (hdr_size < 8 || hdr_size > buf_size) {
 +        av_log(avctx, AV_LOG_ERROR, "error, wrong picture header size\n");
 +        return -1;
 +    }
 +
 +    pic_data_size = AV_RB32(buf + 1);
 +    if (pic_data_size > buf_size) {
 +        av_log(avctx, AV_LOG_ERROR, "error, wrong picture data size\n");
 +        return -1;
 +    }
 +
 +    log2_slice_mb_width  = buf[7] >> 4;
 +    log2_slice_mb_height = buf[7] & 0xF;
 +    if (log2_slice_mb_width > 3 || log2_slice_mb_height) {
 +        av_log(avctx, AV_LOG_ERROR, "unsupported slice resolution: %dx%d\n",
 +               1 << log2_slice_mb_width, 1 << log2_slice_mb_height);
 +        return -1;
 +    }
 +
 +    ctx->mb_width  = (avctx->width  + 15) >> 4;
 +    if (ctx->frame_type)
 +        ctx->mb_height = (avctx->height + 31) >> 5;
 +    else
 +        ctx->mb_height = (avctx->height + 15) >> 4;
 +
 +    slice_count = AV_RB16(buf + 5);
 +
 +    if (ctx->slice_count != slice_count || !ctx->slices) {
 +        av_freep(&ctx->slices);
 +        ctx->slices = av_mallocz(slice_count * sizeof(*ctx->slices));
 +        if (!ctx->slices)
 +            return AVERROR(ENOMEM);
 +        ctx->slice_count = slice_count;
 +    }
 +
 +    if (!slice_count)
 +        return AVERROR(EINVAL);
 +
 +    if (hdr_size + slice_count*2 > buf_size) {
 +        av_log(avctx, AV_LOG_ERROR, "error, wrong slice count\n");
 +        return -1;
 +    }
 +
 +    // parse slice information
 +    index_ptr = buf + hdr_size;
 +    data_ptr  = index_ptr + slice_count*2;
 +
 +    slice_mb_count = 1 << log2_slice_mb_width;
 +    mb_x = 0;
 +    mb_y = 0;
 +
 +    for (i = 0; i < slice_count; i++) {
 +        SliceContext *slice = &ctx->slices[i];
 +
 +        slice->data = data_ptr;
 +        data_ptr += AV_RB16(index_ptr + i*2);
 +
 +        while (ctx->mb_width - mb_x < slice_mb_count)
 +            slice_mb_count >>= 1;
 +
 +        slice->mb_x = mb_x;
 +        slice->mb_y = mb_y;
 +        slice->mb_count = slice_mb_count;
 +        slice->data_size = data_ptr - slice->data;
 +
 +        if (slice->data_size < 6) {
 +            av_log(avctx, AV_LOG_ERROR, "error, wrong slice data size\n");
 +            return -1;
 +        }
 +
 +        mb_x += slice_mb_count;
 +        if (mb_x == ctx->mb_width) {
 +            slice_mb_count = 1 << log2_slice_mb_width;
 +            mb_x = 0;
 +            mb_y++;
 +        }
 +        if (data_ptr > buf + buf_size) {
 +            av_log(avctx, AV_LOG_ERROR, "error, slice out of bounds\n");
 +            return -1;
 +        }
 +    }
 +
 +    if (mb_x || mb_y != ctx->mb_height) {
 +        av_log(avctx, AV_LOG_ERROR, "error wrong mb count y %d h %d\n",
 +               mb_y, ctx->mb_height);
 +        return -1;
 +    }
 +
 +    return pic_data_size;
 +}
 +
 +#define DECODE_CODEWORD(val, codebook)                                  \
 +    do {                                                                \
 +        unsigned int rice_order, exp_order, switch_bits;                \
 +        unsigned int q, buf, bits;                                      \
 +                                                                        \
 +        UPDATE_CACHE(re, gb);                                           \
 +        buf = GET_CACHE(re, gb);                                        \
 +                                                                        \
 +        /* number of bits to switch between rice and exp golomb */      \
 +        switch_bits =  codebook & 3;                                    \
 +        rice_order  =  codebook >> 5;                                   \
 +        exp_order   = (codebook >> 2) & 7;                              \
 +                                                                        \
 +        q = 31 - av_log2(buf);                                          \
 +                                                                        \
 +        if (q > switch_bits) { /* exp golomb */                         \
 +            bits = exp_order - switch_bits + (q<<1);                    \
 +            val = SHOW_UBITS(re, gb, bits) - (1 << exp_order) +         \
 +                ((switch_bits + 1) << rice_order);                      \
 +            SKIP_BITS(re, gb, bits);                                    \
 +        } else if (rice_order) {                                        \
 +            SKIP_BITS(re, gb, q+1);                                     \
 +            val = (q << rice_order) + SHOW_UBITS(re, gb, rice_order);   \
 +            SKIP_BITS(re, gb, rice_order);                              \
 +        } else {                                                        \
 +            val = q;                                                    \
 +            SKIP_BITS(re, gb, q+1);                                     \
 +        }                                                               \
 +    } while (0)
 +
 +#define TOSIGNED(x) (((x) >> 1) ^ (-((x) & 1)))
 +
 +#define FIRST_DC_CB 0xB8
 +
 +static const uint8_t dc_codebook[7] = { 0x04, 0x28, 0x28, 0x4D, 0x4D, 0x70, 0x70};
 +
-     DCTELEM prev_dc;
++static av_always_inline void decode_dc_coeffs(GetBitContext *gb, int16_t *out,
 +                                              int blocks_per_slice)
 +{
-                                               DCTELEM *out, int blocks_per_slice)
++    int16_t prev_dc;
 +    int code, i, sign;
 +
 +    OPEN_READER(re, gb);
 +
 +    DECODE_CODEWORD(code, FIRST_DC_CB);
 +    prev_dc = TOSIGNED(code);
 +    out[0] = prev_dc;
 +
 +    out += 64; // dc coeff for the next block
 +
 +    code = 5;
 +    sign = 0;
 +    for (i = 1; i < blocks_per_slice; i++, out += 64) {
 +        DECODE_CODEWORD(code, dc_codebook[FFMIN(code, 6U)]);
 +        if(code) sign ^= -(code & 1);
 +        else     sign  = 0;
 +        prev_dc += (((code + 1) >> 1) ^ sign) - sign;
 +        out[0] = prev_dc;
 +    }
 +    CLOSE_READER(re, gb);
 +}
 +
 +// adaptive codebook switching lut according to previous run/level values
 +static const uint8_t run_to_cb[16] = { 0x06, 0x06, 0x05, 0x05, 0x04, 0x29, 0x29, 0x29, 0x29, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x4C };
 +static const uint8_t lev_to_cb[10] = { 0x04, 0x0A, 0x05, 0x06, 0x04, 0x28, 0x28, 0x28, 0x28, 0x4C };
 +
 +static av_always_inline void decode_ac_coeffs(AVCodecContext *avctx, GetBitContext *gb,
-     LOCAL_ALIGNED_16(DCTELEM, blocks, [8*4*64]);
-     DCTELEM *block;
++                                              int16_t *out, int blocks_per_slice)
 +{
 +    ProresContext *ctx = avctx->priv_data;
 +    int block_mask, sign;
 +    unsigned pos, run, level;
 +    int max_coeffs, i, bits_left;
 +    int log2_block_count = av_log2(blocks_per_slice);
 +
 +    OPEN_READER(re, gb);
 +    UPDATE_CACHE(re, gb);                                           \
 +    run   = 4;
 +    level = 2;
 +
 +    max_coeffs = 64 << log2_block_count;
 +    block_mask = blocks_per_slice - 1;
 +
 +    for (pos = block_mask;;) {
 +        bits_left = gb->size_in_bits - re_index;
 +        if (!bits_left || (bits_left < 32 && !SHOW_UBITS(re, gb, bits_left)))
 +            break;
 +
 +        DECODE_CODEWORD(run, run_to_cb[FFMIN(run,  15)]);
 +        pos += run + 1;
 +        if (pos >= max_coeffs) {
 +            av_log(avctx, AV_LOG_ERROR, "ac tex damaged %d, %d\n", pos, max_coeffs);
 +            return;
 +        }
 +
 +        DECODE_CODEWORD(level, lev_to_cb[FFMIN(level, 9)]);
 +        level += 1;
 +
 +        i = pos >> log2_block_count;
 +
 +        sign = SHOW_SBITS(re, gb, 1);
 +        SKIP_BITS(re, gb, 1);
 +        out[((pos & block_mask) << 6) + ctx->scan[i]] = ((level ^ sign) - sign);
 +    }
 +
 +    CLOSE_READER(re, gb);
 +}
 +
 +static void decode_slice_luma(AVCodecContext *avctx, SliceContext *slice,
 +                              uint16_t *dst, int dst_stride,
 +                              const uint8_t *buf, unsigned buf_size,
 +                              const int16_t *qmat)
 +{
 +    ProresContext *ctx = avctx->priv_data;
-     LOCAL_ALIGNED_16(DCTELEM, blocks, [8*4*64]);
-     DCTELEM *block;
++    LOCAL_ALIGNED_16(int16_t, blocks, [8*4*64]);
++    int16_t *block;
 +    GetBitContext gb;
 +    int i, blocks_per_slice = slice->mb_count<<2;
 +
 +    for (i = 0; i < blocks_per_slice; i++)
 +        ctx->dsp.clear_block(blocks+(i<<6));
 +
 +    init_get_bits(&gb, buf, buf_size << 3);
 +
 +    decode_dc_coeffs(&gb, blocks, blocks_per_slice);
 +    decode_ac_coeffs(avctx, &gb, blocks, blocks_per_slice);
 +
 +    block = blocks;
 +    for (i = 0; i < slice->mb_count; i++) {
 +        ctx->prodsp.idct_put(dst, dst_stride, block+(0<<6), qmat);
 +        ctx->prodsp.idct_put(dst             +8, dst_stride, block+(1<<6), qmat);
 +        ctx->prodsp.idct_put(dst+4*dst_stride  , dst_stride, block+(2<<6), qmat);
 +        ctx->prodsp.idct_put(dst+4*dst_stride+8, dst_stride, block+(3<<6), qmat);
 +        block += 4*64;
 +        dst += 16;
 +    }
 +}
 +
 +static void decode_slice_chroma(AVCodecContext *avctx, SliceContext *slice,
 +                                uint16_t *dst, int dst_stride,
 +                                const uint8_t *buf, unsigned buf_size,
 +                                const int16_t *qmat, int log2_blocks_per_mb)
 +{
 +    ProresContext *ctx = avctx->priv_data;
++    LOCAL_ALIGNED_16(int16_t, blocks, [8*4*64]);
++    int16_t *block;
 +    GetBitContext gb;
 +    int i, j, blocks_per_slice = slice->mb_count << log2_blocks_per_mb;
 +
 +    for (i = 0; i < blocks_per_slice; i++)
 +        ctx->dsp.clear_block(blocks+(i<<6));
 +
 +    init_get_bits(&gb, buf, buf_size << 3);
 +
 +    decode_dc_coeffs(&gb, blocks, blocks_per_slice);
 +    decode_ac_coeffs(avctx, &gb, blocks, blocks_per_slice);
 +
 +    block = blocks;
 +    for (i = 0; i < slice->mb_count; i++) {
 +        for (j = 0; j < log2_blocks_per_mb; j++) {
 +            ctx->prodsp.idct_put(dst,              dst_stride, block+(0<<6), qmat);
 +            ctx->prodsp.idct_put(dst+4*dst_stride, dst_stride, block+(1<<6), qmat);
 +            block += 2*64;
 +            dst += 8;
 +        }
 +    }
 +}
 +
 +static int decode_slice_thread(AVCodecContext *avctx, void *arg, int jobnr, int threadnr)
 +{
 +    ProresContext *ctx = avctx->priv_data;
 +    SliceContext *slice = &ctx->slices[jobnr];
 +    const uint8_t *buf = slice->data;
 +    AVFrame *pic = avctx->coded_frame;
 +    int i, hdr_size, qscale, log2_chroma_blocks_per_mb;
 +    int luma_stride, chroma_stride;
 +    int y_data_size, u_data_size, v_data_size;
 +    uint8_t *dest_y, *dest_u, *dest_v;
 +    int16_t qmat_luma_scaled[64];
 +    int16_t qmat_chroma_scaled[64];
 +    int mb_x_shift;
 +
 +    slice->ret = -1;
 +    //av_log(avctx, AV_LOG_INFO, "slice %d mb width %d mb x %d y %d\n",
 +    //       jobnr, slice->mb_count, slice->mb_x, slice->mb_y);
 +
 +    // slice header
 +    hdr_size = buf[0] >> 3;
 +    qscale = av_clip(buf[1], 1, 224);
 +    qscale = qscale > 128 ? qscale - 96 << 2: qscale;
 +    y_data_size = AV_RB16(buf + 2);
 +    u_data_size = AV_RB16(buf + 4);
 +    v_data_size = slice->data_size - y_data_size - u_data_size - hdr_size;
 +    if (hdr_size > 7) v_data_size = AV_RB16(buf + 6);
 +
 +    if (y_data_size < 0 || u_data_size < 0 || v_data_size < 0
 +        || hdr_size+y_data_size+u_data_size+v_data_size > slice->data_size){
 +        av_log(avctx, AV_LOG_ERROR, "invalid plane data size\n");
 +        return -1;
 +    }
 +
 +    buf += hdr_size;
 +
 +    for (i = 0; i < 64; i++) {
 +        qmat_luma_scaled  [i] = ctx->qmat_luma  [i] * qscale;
 +        qmat_chroma_scaled[i] = ctx->qmat_chroma[i] * qscale;
 +    }
 +
 +    if (ctx->frame_type == 0) {
 +        luma_stride   = pic->linesize[0];
 +        chroma_stride = pic->linesize[1];
 +    } else {
 +        luma_stride   = pic->linesize[0] << 1;
 +        chroma_stride = pic->linesize[1] << 1;
 +    }
 +
 +    if (avctx->pix_fmt == AV_PIX_FMT_YUV444P10) {
 +        mb_x_shift = 5;
 +        log2_chroma_blocks_per_mb = 2;
 +    } else {
 +        mb_x_shift = 4;
 +        log2_chroma_blocks_per_mb = 1;
 +    }
 +
 +    dest_y = pic->data[0] + (slice->mb_y << 4) * luma_stride + (slice->mb_x << 5);
 +    dest_u = pic->data[1] + (slice->mb_y << 4) * chroma_stride + (slice->mb_x << mb_x_shift);
 +    dest_v = pic->data[2] + (slice->mb_y << 4) * chroma_stride + (slice->mb_x << mb_x_shift);
 +
 +    if (ctx->frame_type && ctx->first_field ^ ctx->frame.top_field_first) {
 +        dest_y += pic->linesize[0];
 +        dest_u += pic->linesize[1];
 +        dest_v += pic->linesize[2];
 +    }
 +
 +    decode_slice_luma(avctx, slice, (uint16_t*)dest_y, luma_stride,
 +                      buf, y_data_size, qmat_luma_scaled);
 +
 +    if (!(avctx->flags & CODEC_FLAG_GRAY)) {
 +        decode_slice_chroma(avctx, slice, (uint16_t*)dest_u, chroma_stride,
 +                            buf + y_data_size, u_data_size,
 +                            qmat_chroma_scaled, log2_chroma_blocks_per_mb);
 +        decode_slice_chroma(avctx, slice, (uint16_t*)dest_v, chroma_stride,
 +                            buf + y_data_size + u_data_size, v_data_size,
 +                            qmat_chroma_scaled, log2_chroma_blocks_per_mb);
 +    }
 +
 +    slice->ret = 0;
 +    return 0;
 +}
 +
 +static int decode_picture(AVCodecContext *avctx)
 +{
 +    ProresContext *ctx = avctx->priv_data;
 +    int i;
 +
 +    avctx->execute2(avctx, decode_slice_thread, NULL, NULL, ctx->slice_count);
 +
 +    for (i = 0; i < ctx->slice_count; i++)
 +        if (ctx->slices[i].ret < 0)
 +            return ctx->slices[i].ret;
 +
 +    return 0;
 +}
 +
 +static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
 +                        AVPacket *avpkt)
 +{
 +    ProresContext *ctx = avctx->priv_data;
 +    AVFrame *frame = avctx->coded_frame;
 +    const uint8_t *buf = avpkt->data;
 +    int buf_size = avpkt->size;
 +    int frame_hdr_size, pic_size;
 +
 +    if (buf_size < 28 || AV_RL32(buf + 4) != AV_RL32("icpf")) {
 +        av_log(avctx, AV_LOG_ERROR, "invalid frame header\n");
 +        return -1;
 +    }
 +
 +    ctx->first_field = 1;
 +
 +    buf += 8;
 +    buf_size -= 8;
 +
 +    frame_hdr_size = decode_frame_header(ctx, buf, buf_size, avctx);
 +    if (frame_hdr_size < 0)
 +        return -1;
 +
 +    buf += frame_hdr_size;
 +    buf_size -= frame_hdr_size;
 +
 +    if (frame->data[0])
 +        avctx->release_buffer(avctx, frame);
 +
 +    if (ff_get_buffer(avctx, frame) < 0)
 +        return -1;
 +
 + decode_picture:
 +    pic_size = decode_picture_header(avctx, buf, buf_size);
 +    if (pic_size < 0) {
 +        av_log(avctx, AV_LOG_ERROR, "error decoding picture header\n");
 +        return -1;
 +    }
 +
 +    if (decode_picture(avctx)) {
 +        av_log(avctx, AV_LOG_ERROR, "error decoding picture\n");
 +        return -1;
 +    }
 +
 +    buf += pic_size;
 +    buf_size -= pic_size;
 +
 +    if (ctx->frame_type && buf_size > 0 && ctx->first_field) {
 +        ctx->first_field = 0;
 +        goto decode_picture;
 +    }
 +
 +    *got_frame      = 1;
 +    *(AVFrame*)data = *frame;
 +
 +    return avpkt->size;
 +}
 +
 +static av_cold int decode_close(AVCodecContext *avctx)
 +{
 +    ProresContext *ctx = avctx->priv_data;
 +
 +    AVFrame *frame = avctx->coded_frame;
 +    if (frame->data[0])
 +        avctx->release_buffer(avctx, frame);
 +    av_freep(&ctx->slices);
 +
 +    return 0;
 +}
 +
 +AVCodec ff_prores_decoder = {
 +    .name           = "prores",
 +    .type           = AVMEDIA_TYPE_VIDEO,
 +    .id             = AV_CODEC_ID_PRORES,
 +    .priv_data_size = sizeof(ProresContext),
 +    .init           = decode_init,
 +    .close          = decode_close,
 +    .decode         = decode_frame,
 +    .long_name      = NULL_IF_CONFIG_SMALL("ProRes"),
 +    .capabilities   = CODEC_CAP_DR1 | CODEC_CAP_SLICE_THREADS,
 +};
index a25ecca,0000000..5c53882
mode 100644,000000..100644
--- /dev/null
@@@ -1,676 -1,0 +1,677 @@@
-     DECLARE_ALIGNED(16, DCTELEM, blocks)[8 * 4 * 64];
 +/*
 + * Apple ProRes compatible decoder
 + *
 + * Copyright (c) 2010-2011 Maxim Poliakovski
 + *
 + * This file is part of Libav.
 + *
 + * Libav is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU Lesser General Public
 + * License as published by the Free Software Foundation; either
 + * version 2.1 of the License, or (at your option) any later version.
 + *
 + * Libav is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * Lesser General Public License for more details.
 + *
 + * You should have received a copy of the GNU Lesser General Public
 + * License along with Libav; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
 +/**
 + * @file
 + * This is a decoder for Apple ProRes 422 SD/HQ/LT/Proxy and ProRes 4444.
 + * It is used for storing and editing high definition video data in Apple's Final Cut Pro.
 + *
 + * @see http://wiki.multimedia.cx/index.php?title=Apple_ProRes
 + */
 +
 +#define LONG_BITSTREAM_READER // some ProRes vlc codes require up to 28 bits to be read at once
 +
 +#include <stdint.h>
 +
 +#include "libavutil/intmath.h"
 +#include "avcodec.h"
++#include "dsputil.h"
 +#include "internal.h"
 +#include "proresdata.h"
 +#include "proresdsp.h"
 +#include "get_bits.h"
 +
 +typedef struct {
 +    const uint8_t *index;            ///< pointers to the data of this slice
 +    int slice_num;
 +    int x_pos, y_pos;
 +    int slice_width;
 +    int prev_slice_sf;               ///< scalefactor of the previous decoded slice
- static inline void decode_dc_coeffs(GetBitContext *gb, DCTELEM *out,
++    DECLARE_ALIGNED(16, int16_t, blocks)[8 * 4 * 64];
 +    DECLARE_ALIGNED(16, int16_t, qmat_luma_scaled)[64];
 +    DECLARE_ALIGNED(16, int16_t, qmat_chroma_scaled)[64];
 +} ProresThreadData;
 +
 +typedef struct {
 +    ProresDSPContext dsp;
 +    AVFrame    picture;
 +    ScanTable  scantable;
 +    int        scantable_type;           ///< -1 = uninitialized, 0 = progressive, 1/2 = interlaced
 +
 +    int        frame_type;               ///< 0 = progressive, 1 = top-field first, 2 = bottom-field first
 +    int        pic_format;               ///< 2 = 422, 3 = 444
 +    uint8_t    qmat_luma[64];            ///< dequantization matrix for luma
 +    uint8_t    qmat_chroma[64];          ///< dequantization matrix for chroma
 +    int        qmat_changed;             ///< 1 - global quantization matrices changed
 +    int        total_slices;            ///< total number of slices in a picture
 +    ProresThreadData *slice_data;
 +    int        pic_num;
 +    int        chroma_factor;
 +    int        mb_chroma_factor;
 +    int        num_chroma_blocks;       ///< number of chrominance blocks in a macroblock
 +    int        num_x_slices;
 +    int        num_y_slices;
 +    int        slice_width_factor;
 +    int        slice_height_factor;
 +    int        num_x_mbs;
 +    int        num_y_mbs;
 +    int        alpha_info;
 +} ProresContext;
 +
 +
 +static av_cold int decode_init(AVCodecContext *avctx)
 +{
 +    ProresContext *ctx = avctx->priv_data;
 +
 +    ctx->total_slices     = 0;
 +    ctx->slice_data       = NULL;
 +
 +    avctx->bits_per_raw_sample = PRORES_BITS_PER_SAMPLE;
 +    ff_proresdsp_init(&ctx->dsp, avctx);
 +
 +    avctx->coded_frame = &ctx->picture;
 +    avcodec_get_frame_defaults(&ctx->picture);
 +    ctx->picture.type      = AV_PICTURE_TYPE_I;
 +    ctx->picture.key_frame = 1;
 +
 +    ctx->scantable_type = -1;   // set scantable type to uninitialized
 +    memset(ctx->qmat_luma, 4, 64);
 +    memset(ctx->qmat_chroma, 4, 64);
 +
 +    return 0;
 +}
 +
 +
 +static int decode_frame_header(ProresContext *ctx, const uint8_t *buf,
 +                               const int data_size, AVCodecContext *avctx)
 +{
 +    int hdr_size, version, width, height, flags;
 +    const uint8_t *ptr;
 +
 +    hdr_size = AV_RB16(buf);
 +    if (hdr_size > data_size) {
 +        av_log(avctx, AV_LOG_ERROR, "frame data too small\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    version = AV_RB16(buf + 2);
 +    if (version >= 2) {
 +        av_log(avctx, AV_LOG_ERROR,
 +               "unsupported header version: %d\n", version);
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    width  = AV_RB16(buf + 8);
 +    height = AV_RB16(buf + 10);
 +    if (width != avctx->width || height != avctx->height) {
 +        av_log(avctx, AV_LOG_ERROR,
 +               "picture dimension changed: old: %d x %d, new: %d x %d\n",
 +               avctx->width, avctx->height, width, height);
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    ctx->frame_type = (buf[12] >> 2) & 3;
 +    if (ctx->frame_type > 2) {
 +        av_log(avctx, AV_LOG_ERROR,
 +               "unsupported frame type: %d\n", ctx->frame_type);
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    ctx->chroma_factor     = (buf[12] >> 6) & 3;
 +    ctx->mb_chroma_factor  = ctx->chroma_factor + 2;
 +    ctx->num_chroma_blocks = (1 << ctx->chroma_factor) >> 1;
 +    switch (ctx->chroma_factor) {
 +    case 2:
 +        avctx->pix_fmt = AV_PIX_FMT_YUV422P10;
 +        break;
 +    case 3:
 +        avctx->pix_fmt = AV_PIX_FMT_YUV444P10;
 +        break;
 +    default:
 +        av_log(avctx, AV_LOG_ERROR,
 +               "unsupported picture format: %d\n", ctx->pic_format);
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    if (ctx->scantable_type != ctx->frame_type) {
 +        if (!ctx->frame_type)
 +            ff_init_scantable(ctx->dsp.idct_permutation, &ctx->scantable,
 +                              ff_prores_progressive_scan);
 +        else
 +            ff_init_scantable(ctx->dsp.idct_permutation, &ctx->scantable,
 +                              ff_prores_interlaced_scan);
 +        ctx->scantable_type = ctx->frame_type;
 +    }
 +
 +    if (ctx->frame_type) {      /* if interlaced */
 +        ctx->picture.interlaced_frame = 1;
 +        ctx->picture.top_field_first  = ctx->frame_type & 1;
 +    } else {
 +        ctx->picture.interlaced_frame = 0;
 +    }
 +
 +    avctx->color_primaries = buf[14];
 +    avctx->color_trc       = buf[15];
 +    avctx->colorspace      = buf[16];
 +
 +    ctx->alpha_info = buf[17] & 0xf;
 +    if (ctx->alpha_info)
 +        av_log_missing_feature(avctx, "Alpha channel", 0);
 +
 +    ctx->qmat_changed = 0;
 +    ptr   = buf + 20;
 +    flags = buf[19];
 +    if (flags & 2) {
 +        if (ptr - buf > hdr_size - 64) {
 +            av_log(avctx, AV_LOG_ERROR, "header data too small\n");
 +            return AVERROR_INVALIDDATA;
 +        }
 +        if (memcmp(ctx->qmat_luma, ptr, 64)) {
 +            memcpy(ctx->qmat_luma, ptr, 64);
 +            ctx->qmat_changed = 1;
 +        }
 +        ptr += 64;
 +    } else {
 +        memset(ctx->qmat_luma, 4, 64);
 +        ctx->qmat_changed = 1;
 +    }
 +
 +    if (flags & 1) {
 +        if (ptr - buf > hdr_size - 64) {
 +            av_log(avctx, AV_LOG_ERROR, "header data too small\n");
 +            return -1;
 +        }
 +        if (memcmp(ctx->qmat_chroma, ptr, 64)) {
 +            memcpy(ctx->qmat_chroma, ptr, 64);
 +            ctx->qmat_changed = 1;
 +        }
 +    } else {
 +        memset(ctx->qmat_chroma, 4, 64);
 +        ctx->qmat_changed = 1;
 +    }
 +
 +    return hdr_size;
 +}
 +
 +
 +static int decode_picture_header(ProresContext *ctx, const uint8_t *buf,
 +                                 const int data_size, AVCodecContext *avctx)
 +{
 +    int   i, hdr_size, pic_data_size, num_slices;
 +    int   slice_width_factor, slice_height_factor;
 +    int   remainder, num_x_slices;
 +    const uint8_t *data_ptr, *index_ptr;
 +
 +    hdr_size = data_size > 0 ? buf[0] >> 3 : 0;
 +    if (hdr_size < 8 || hdr_size > data_size) {
 +        av_log(avctx, AV_LOG_ERROR, "picture header too small\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    pic_data_size = AV_RB32(buf + 1);
 +    if (pic_data_size > data_size) {
 +        av_log(avctx, AV_LOG_ERROR, "picture data too small\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    slice_width_factor  = buf[7] >> 4;
 +    slice_height_factor = buf[7] & 0xF;
 +    if (slice_width_factor > 3 || slice_height_factor) {
 +        av_log(avctx, AV_LOG_ERROR,
 +               "unsupported slice dimension: %d x %d\n",
 +               1 << slice_width_factor, 1 << slice_height_factor);
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    ctx->slice_width_factor  = slice_width_factor;
 +    ctx->slice_height_factor = slice_height_factor;
 +
 +    ctx->num_x_mbs = (avctx->width + 15) >> 4;
 +    ctx->num_y_mbs = (avctx->height +
 +                      (1 << (4 + ctx->picture.interlaced_frame)) - 1) >>
 +                     (4 + ctx->picture.interlaced_frame);
 +
 +    remainder    = ctx->num_x_mbs & ((1 << slice_width_factor) - 1);
 +    num_x_slices = (ctx->num_x_mbs >> slice_width_factor) + (remainder & 1) +
 +                   ((remainder >> 1) & 1) + ((remainder >> 2) & 1);
 +
 +    num_slices = num_x_slices * ctx->num_y_mbs;
 +    if (num_slices != AV_RB16(buf + 5)) {
 +        av_log(avctx, AV_LOG_ERROR, "invalid number of slices\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    if (ctx->total_slices != num_slices) {
 +        av_freep(&ctx->slice_data);
 +        ctx->slice_data = av_malloc((num_slices + 1) * sizeof(ctx->slice_data[0]));
 +        if (!ctx->slice_data)
 +            return AVERROR(ENOMEM);
 +        ctx->total_slices = num_slices;
 +    }
 +
 +    if (hdr_size + num_slices * 2 > data_size) {
 +        av_log(avctx, AV_LOG_ERROR, "slice table too small\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    /* parse slice table allowing quick access to the slice data */
 +    index_ptr = buf + hdr_size;
 +    data_ptr = index_ptr + num_slices * 2;
 +
 +    for (i = 0; i < num_slices; i++) {
 +        ctx->slice_data[i].index = data_ptr;
 +        ctx->slice_data[i].prev_slice_sf = 0;
 +        data_ptr += AV_RB16(index_ptr + i * 2);
 +    }
 +    ctx->slice_data[i].index = data_ptr;
 +    ctx->slice_data[i].prev_slice_sf = 0;
 +
 +    if (data_ptr > buf + data_size) {
 +        av_log(avctx, AV_LOG_ERROR, "out of slice data\n");
 +        return -1;
 +    }
 +
 +    return pic_data_size;
 +}
 +
 +
 +/**
 + * Read an unsigned rice/exp golomb codeword.
 + */
 +static inline int decode_vlc_codeword(GetBitContext *gb, unsigned codebook)
 +{
 +    unsigned int rice_order, exp_order, switch_bits;
 +    unsigned int buf, code;
 +    int log, prefix_len, len;
 +
 +    OPEN_READER(re, gb);
 +    UPDATE_CACHE(re, gb);
 +    buf = GET_CACHE(re, gb);
 +
 +    /* number of prefix bits to switch between Rice and expGolomb */
 +    switch_bits = (codebook & 3) + 1;
 +    rice_order  = codebook >> 5;        /* rice code order */
 +    exp_order   = (codebook >> 2) & 7;  /* exp golomb code order */
 +
 +    log = 31 - av_log2(buf); /* count prefix bits (zeroes) */
 +
 +    if (log < switch_bits) { /* ok, we got a rice code */
 +        if (!rice_order) {
 +            /* shortcut for faster decoding of rice codes without remainder */
 +            code = log;
 +            LAST_SKIP_BITS(re, gb, log + 1);
 +        } else {
 +            prefix_len = log + 1;
 +            code = (log << rice_order) + NEG_USR32(buf << prefix_len, rice_order);
 +            LAST_SKIP_BITS(re, gb, prefix_len + rice_order);
 +        }
 +    } else { /* otherwise we got a exp golomb code */
 +        len  = (log << 1) - switch_bits + exp_order + 1;
 +        code = NEG_USR32(buf, len) - (1 << exp_order) + (switch_bits << rice_order);
 +        LAST_SKIP_BITS(re, gb, len);
 +    }
 +
 +    CLOSE_READER(re, gb);
 +
 +    return code;
 +}
 +
 +#define LSB2SIGN(x) (-((x) & 1))
 +#define TOSIGNED(x) (((x) >> 1) ^ LSB2SIGN(x))
 +
 +/**
 + * Decode DC coefficients for all blocks in a slice.
 + */
-     DCTELEM prev_dc;
++static inline void decode_dc_coeffs(GetBitContext *gb, int16_t *out,
 +                                    int nblocks)
 +{
- static inline void decode_ac_coeffs(GetBitContext *gb, DCTELEM *out,
++    int16_t prev_dc;
 +    int     i, sign;
 +    int16_t delta;
 +    unsigned int code;
 +
 +    code   = decode_vlc_codeword(gb, FIRST_DC_CB);
 +    out[0] = prev_dc = TOSIGNED(code);
 +
 +    out   += 64; /* move to the DC coeff of the next block */
 +    delta  = 3;
 +
 +    for (i = 1; i < nblocks; i++, out += 64) {
 +        code = decode_vlc_codeword(gb, ff_prores_dc_codebook[FFMIN(FFABS(delta), 3)]);
 +
 +        sign     = -(((delta >> 15) & 1) ^ (code & 1));
 +        delta    = (((code + 1) >> 1) ^ sign) - sign;
 +        prev_dc += delta;
 +        out[0]   = prev_dc;
 +    }
 +}
 +
 +
 +/**
 + * Decode AC coefficients for all blocks in a slice.
 + */
-     DCTELEM *block_ptr;
++static inline void decode_ac_coeffs(GetBitContext *gb, int16_t *out,
 +                                    int blocks_per_slice,
 +                                    int plane_size_factor,
 +                                    const uint8_t *scan)
 +{
 +    int pos, block_mask, run, level, sign, run_cb_index, lev_cb_index;
 +    int max_coeffs, bits_left;
 +
 +    /* set initial prediction values */
 +    run   = 4;
 +    level = 2;
 +
 +    max_coeffs = blocks_per_slice << 6;
 +    block_mask = blocks_per_slice - 1;
 +
 +    for (pos = blocks_per_slice - 1; pos < max_coeffs;) {
 +        run_cb_index = ff_prores_run_to_cb_index[FFMIN(run, 15)];
 +        lev_cb_index = ff_prores_lev_to_cb_index[FFMIN(level, 9)];
 +
 +        bits_left = get_bits_left(gb);
 +        if (bits_left <= 0 || (bits_left <= 8 && !show_bits(gb, bits_left)))
 +            return;
 +
 +        run = decode_vlc_codeword(gb, ff_prores_ac_codebook[run_cb_index]);
 +
 +        bits_left = get_bits_left(gb);
 +        if (bits_left <= 0 || (bits_left <= 8 && !show_bits(gb, bits_left)))
 +            return;
 +
 +        level = decode_vlc_codeword(gb, ff_prores_ac_codebook[lev_cb_index]) + 1;
 +
 +        pos += run + 1;
 +        if (pos >= max_coeffs)
 +            break;
 +
 +        sign = get_sbits(gb, 1);
 +        out[((pos & block_mask) << 6) + scan[pos >> plane_size_factor]] =
 +            (level ^ sign) - sign;
 +    }
 +}
 +
 +
 +/**
 + * Decode a slice plane (luma or chroma).
 + */
 +static void decode_slice_plane(ProresContext *ctx, ProresThreadData *td,
 +                               const uint8_t *buf,
 +                               int data_size, uint16_t *out_ptr,
 +                               int linesize, int mbs_per_slice,
 +                               int blocks_per_mb, int plane_size_factor,
 +                               const int16_t *qmat, int is_chroma)
 +{
 +    GetBitContext gb;
++    int16_t *block_ptr;
 +    int mb_num, blocks_per_slice;
 +
 +    blocks_per_slice = mbs_per_slice * blocks_per_mb;
 +
 +    memset(td->blocks, 0, 8 * 4 * 64 * sizeof(*td->blocks));
 +
 +    init_get_bits(&gb, buf, data_size << 3);
 +
 +    decode_dc_coeffs(&gb, td->blocks, blocks_per_slice);
 +
 +    decode_ac_coeffs(&gb, td->blocks, blocks_per_slice,
 +                     plane_size_factor, ctx->scantable.permutated);
 +
 +    /* inverse quantization, inverse transform and output */
 +    block_ptr = td->blocks;
 +
 +    if (!is_chroma) {
 +        for (mb_num = 0; mb_num < mbs_per_slice; mb_num++, out_ptr += blocks_per_mb * 4) {
 +            ctx->dsp.idct_put(out_ptr,                    linesize, block_ptr, qmat);
 +            block_ptr += 64;
 +            if (blocks_per_mb > 2) {
 +                ctx->dsp.idct_put(out_ptr + 8,            linesize, block_ptr, qmat);
 +                block_ptr += 64;
 +            }
 +            ctx->dsp.idct_put(out_ptr + linesize * 4,     linesize, block_ptr, qmat);
 +            block_ptr += 64;
 +            if (blocks_per_mb > 2) {
 +                ctx->dsp.idct_put(out_ptr + linesize * 4 + 8, linesize, block_ptr, qmat);
 +                block_ptr += 64;
 +            }
 +        }
 +    } else {
 +        for (mb_num = 0; mb_num < mbs_per_slice; mb_num++, out_ptr += blocks_per_mb * 4) {
 +            ctx->dsp.idct_put(out_ptr,                    linesize, block_ptr, qmat);
 +            block_ptr += 64;
 +            ctx->dsp.idct_put(out_ptr + linesize * 4,     linesize, block_ptr, qmat);
 +            block_ptr += 64;
 +            if (blocks_per_mb > 2) {
 +                ctx->dsp.idct_put(out_ptr + 8,            linesize, block_ptr, qmat);
 +                block_ptr += 64;
 +                ctx->dsp.idct_put(out_ptr + linesize * 4 + 8, linesize, block_ptr, qmat);
 +                block_ptr += 64;
 +            }
 +        }
 +    }
 +}
 +
 +
 +static int decode_slice(AVCodecContext *avctx, void *tdata)
 +{
 +    ProresThreadData *td = tdata;
 +    ProresContext *ctx = avctx->priv_data;
 +    int mb_x_pos  = td->x_pos;
 +    int mb_y_pos  = td->y_pos;
 +    int pic_num   = ctx->pic_num;
 +    int slice_num = td->slice_num;
 +    int mbs_per_slice = td->slice_width;
 +    const uint8_t *buf;
 +    uint8_t *y_data, *u_data, *v_data;
 +    AVFrame *pic = avctx->coded_frame;
 +    int i, sf, slice_width_factor;
 +    int slice_data_size, hdr_size, y_data_size, u_data_size, v_data_size;
 +    int y_linesize, u_linesize, v_linesize;
 +
 +    buf             = ctx->slice_data[slice_num].index;
 +    slice_data_size = ctx->slice_data[slice_num + 1].index - buf;
 +
 +    slice_width_factor = av_log2(mbs_per_slice);
 +
 +    y_data     = pic->data[0];
 +    u_data     = pic->data[1];
 +    v_data     = pic->data[2];
 +    y_linesize = pic->linesize[0];
 +    u_linesize = pic->linesize[1];
 +    v_linesize = pic->linesize[2];
 +
 +    if (pic->interlaced_frame) {
 +        if (!(pic_num ^ pic->top_field_first)) {
 +            y_data += y_linesize;
 +            u_data += u_linesize;
 +            v_data += v_linesize;
 +        }
 +        y_linesize <<= 1;
 +        u_linesize <<= 1;
 +        v_linesize <<= 1;
 +    }
 +
 +    if (slice_data_size < 6) {
 +        av_log(avctx, AV_LOG_ERROR, "slice data too small\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    /* parse slice header */
 +    hdr_size    = buf[0] >> 3;
 +    y_data_size = AV_RB16(buf + 2);
 +    u_data_size = AV_RB16(buf + 4);
 +    v_data_size = hdr_size > 7 ? AV_RB16(buf + 6) :
 +        slice_data_size - y_data_size - u_data_size - hdr_size;
 +
 +    if (hdr_size + y_data_size + u_data_size + v_data_size > slice_data_size ||
 +        v_data_size < 0 || hdr_size < 6) {
 +        av_log(avctx, AV_LOG_ERROR, "invalid data size\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    sf = av_clip(buf[1], 1, 224);
 +    sf = sf > 128 ? (sf - 96) << 2 : sf;
 +
 +    /* scale quantization matrixes according with slice's scale factor */
 +    /* TODO: this can be SIMD-optimized a lot */
 +    if (ctx->qmat_changed || sf != td->prev_slice_sf) {
 +        td->prev_slice_sf = sf;
 +        for (i = 0; i < 64; i++) {
 +            td->qmat_luma_scaled[ctx->dsp.idct_permutation[i]]   = ctx->qmat_luma[i]   * sf;
 +            td->qmat_chroma_scaled[ctx->dsp.idct_permutation[i]] = ctx->qmat_chroma[i] * sf;
 +        }
 +    }
 +
 +    /* decode luma plane */
 +    decode_slice_plane(ctx, td, buf + hdr_size, y_data_size,
 +                       (uint16_t*) (y_data + (mb_y_pos << 4) * y_linesize +
 +                                    (mb_x_pos << 5)), y_linesize,
 +                       mbs_per_slice, 4, slice_width_factor + 2,
 +                       td->qmat_luma_scaled, 0);
 +
 +    /* decode U chroma plane */
 +    decode_slice_plane(ctx, td, buf + hdr_size + y_data_size, u_data_size,
 +                       (uint16_t*) (u_data + (mb_y_pos << 4) * u_linesize +
 +                                    (mb_x_pos << ctx->mb_chroma_factor)),
 +                       u_linesize, mbs_per_slice, ctx->num_chroma_blocks,
 +                       slice_width_factor + ctx->chroma_factor - 1,
 +                       td->qmat_chroma_scaled, 1);
 +
 +    /* decode V chroma plane */
 +    decode_slice_plane(ctx, td, buf + hdr_size + y_data_size + u_data_size,
 +                       v_data_size,
 +                       (uint16_t*) (v_data + (mb_y_pos << 4) * v_linesize +
 +                                    (mb_x_pos << ctx->mb_chroma_factor)),
 +                       v_linesize, mbs_per_slice, ctx->num_chroma_blocks,
 +                       slice_width_factor + ctx->chroma_factor - 1,
 +                       td->qmat_chroma_scaled, 1);
 +
 +    return 0;
 +}
 +
 +
 +static int decode_picture(ProresContext *ctx, int pic_num,
 +                          AVCodecContext *avctx)
 +{
 +    int slice_num, slice_width, x_pos, y_pos;
 +
 +    slice_num = 0;
 +
 +    ctx->pic_num = pic_num;
 +    for (y_pos = 0; y_pos < ctx->num_y_mbs; y_pos++) {
 +        slice_width = 1 << ctx->slice_width_factor;
 +
 +        for (x_pos = 0; x_pos < ctx->num_x_mbs && slice_width;
 +             x_pos += slice_width) {
 +            while (ctx->num_x_mbs - x_pos < slice_width)
 +                slice_width >>= 1;
 +
 +            ctx->slice_data[slice_num].slice_num   = slice_num;
 +            ctx->slice_data[slice_num].x_pos       = x_pos;
 +            ctx->slice_data[slice_num].y_pos       = y_pos;
 +            ctx->slice_data[slice_num].slice_width = slice_width;
 +
 +            slice_num++;
 +        }
 +    }
 +
 +    return avctx->execute(avctx, decode_slice,
 +                          ctx->slice_data, NULL, slice_num,
 +                          sizeof(ctx->slice_data[0]));
 +}
 +
 +
 +#define MOVE_DATA_PTR(nbytes) buf += (nbytes); buf_size -= (nbytes)
 +
 +static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
 +                        AVPacket *avpkt)
 +{
 +    ProresContext *ctx = avctx->priv_data;
 +    AVFrame *picture   = avctx->coded_frame;
 +    const uint8_t *buf = avpkt->data;
 +    int buf_size       = avpkt->size;
 +    int frame_hdr_size, pic_num, pic_data_size;
 +
 +    /* check frame atom container */
 +    if (buf_size < 28 || buf_size < AV_RB32(buf) ||
 +        AV_RB32(buf + 4) != FRAME_ID) {
 +        av_log(avctx, AV_LOG_ERROR, "invalid frame\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    MOVE_DATA_PTR(8);
 +
 +    frame_hdr_size = decode_frame_header(ctx, buf, buf_size, avctx);
 +    if (frame_hdr_size < 0)
 +        return AVERROR_INVALIDDATA;
 +
 +    MOVE_DATA_PTR(frame_hdr_size);
 +
 +    if (picture->data[0])
 +        avctx->release_buffer(avctx, picture);
 +
 +    picture->reference = 0;
 +    if (ff_get_buffer(avctx, picture) < 0)
 +        return -1;
 +
 +    for (pic_num = 0; ctx->picture.interlaced_frame - pic_num + 1; pic_num++) {
 +        pic_data_size = decode_picture_header(ctx, buf, buf_size, avctx);
 +        if (pic_data_size < 0)
 +            return AVERROR_INVALIDDATA;
 +
 +        if (decode_picture(ctx, pic_num, avctx))
 +            return -1;
 +
 +        MOVE_DATA_PTR(pic_data_size);
 +    }
 +
 +    *got_frame       = 1;
 +    *(AVFrame*) data = *avctx->coded_frame;
 +
 +    return avpkt->size;
 +}
 +
 +
 +static av_cold int decode_close(AVCodecContext *avctx)
 +{
 +    ProresContext *ctx = avctx->priv_data;
 +
 +    if (ctx->picture.data[0])
 +        avctx->release_buffer(avctx, &ctx->picture);
 +
 +    av_freep(&ctx->slice_data);
 +
 +    return 0;
 +}
 +
 +
 +AVCodec ff_prores_lgpl_decoder = {
 +    .name           = "prores_lgpl",
 +    .type           = AVMEDIA_TYPE_VIDEO,
 +    .id             = AV_CODEC_ID_PRORES,
 +    .priv_data_size = sizeof(ProresContext),
 +    .init           = decode_init,
 +    .close          = decode_close,
 +    .decode         = decode_frame,
 +    .capabilities   = CODEC_CAP_DR1 | CODEC_CAP_SLICE_THREADS,
 +    .long_name      = NULL_IF_CONFIG_SMALL("Apple ProRes (iCodec Pro)")
 +};
@@@ -54,8 -55,8 +55,8 @@@ static void prores_idct_put_c(uint16_t 
  }
  #endif
  
 -#if CONFIG_PRORES_ENCODER
 +#if CONFIG_PRORES_KOSTYA_ENCODER
- static void prores_fdct_c(const uint16_t *src, int linesize, DCTELEM *block)
+ static void prores_fdct_c(const uint16_t *src, int linesize, int16_t *block)
  {
      int x, y;
      const uint16_t *tsrc = src;
@@@ -32,12 -32,12 +32,12 @@@ typedef struct ProresDSPContext 
      uint8_t idct_permutation[64];
      int dct_permutation_type;
      uint8_t dct_permutation[64];
-     void (* idct_put) (uint16_t *out, int linesize, DCTELEM *block, const int16_t *qmat);
-     void (* fdct) (const uint16_t *src, int linesize, DCTELEM *block);
+     void (* idct_put) (uint16_t *out, int linesize, int16_t *block, const int16_t *qmat);
+     void (* fdct) (const uint16_t *src, int linesize, int16_t *block);
  } ProresDSPContext;
  
 -void ff_proresdsp_init(ProresDSPContext *dsp);
 +void ff_proresdsp_init(ProresDSPContext *dsp, AVCodecContext *avctx);
  
 -void ff_proresdsp_x86_init(ProresDSPContext *dsp);
 +void ff_proresdsp_x86_init(ProresDSPContext *dsp, AVCodecContext *avctx);
  
  #endif /* AVCODEC_PRORESDSP_H */
index 8c71ca5,0000000..1e73757
mode 100644,000000..100644
--- /dev/null
@@@ -1,625 -1,0 +1,625 @@@
- static void encode_dc_coeffs(PutBitContext *pb, DCTELEM *in,
 +/*
 + * Apple ProRes encoder
 + *
 + * Copyright (c) 2011 Anatoliy Wasserman
 + *
 + * This file is part of FFmpeg.
 + *
 + * FFmpeg is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU Lesser General Public
 + * License as published by the Free Software Foundation; either
 + * version 2.1 of the License, or (at your option) any later version.
 + *
 + * FFmpeg is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * Lesser General Public License for more details.
 + *
 + * You should have received a copy of the GNU Lesser General Public
 + * License along with FFmpeg; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
 +/**
 + * @file
 + * Apple ProRes encoder (Anatoliy Wasserman version)
 + * Known FOURCCs: 'apch' (HQ), 'apcn' (SD), 'apcs' (LT), 'acpo' (Proxy)
 + */
 +
 +#include "avcodec.h"
 +#include "internal.h"
 +#include "put_bits.h"
 +#include "bytestream.h"
 +#include "dsputil.h"
 +
 +#define DEFAULT_SLICE_MB_WIDTH 8
 +
 +#define FF_PROFILE_PRORES_PROXY     0
 +#define FF_PROFILE_PRORES_LT        1
 +#define FF_PROFILE_PRORES_STANDARD  2
 +#define FF_PROFILE_PRORES_HQ        3
 +
 +static const AVProfile profiles[] = {
 +    { FF_PROFILE_PRORES_PROXY,    "apco"},
 +    { FF_PROFILE_PRORES_LT,       "apcs"},
 +    { FF_PROFILE_PRORES_STANDARD, "apcn"},
 +    { FF_PROFILE_PRORES_HQ,       "apch"},
 +    { FF_PROFILE_UNKNOWN }
 +};
 +
 +static const int qp_start_table[4] = { 4, 1, 1, 1 };
 +static const int qp_end_table[4]   = { 8, 9, 6, 6 };
 +static const int bitrate_table[5]  = { 1000, 2100, 3500, 5400 };
 +
 +static const uint8_t progressive_scan[64] = {
 +     0,  1,  8,  9,  2,  3, 10, 11,
 +    16, 17, 24, 25, 18, 19, 26, 27,
 +     4,  5, 12, 20, 13,  6,  7, 14,
 +    21, 28, 29, 22, 15, 23, 30, 31,
 +    32, 33, 40, 48, 41, 34, 35, 42,
 +    49, 56, 57, 50, 43, 36, 37, 44,
 +    51, 58, 59, 52, 45, 38, 39, 46,
 +    53, 60, 61, 54, 47, 55, 62, 63
 +};
 +
 +static const uint8_t QMAT_LUMA[4][64] = {
 +    {
 +         4,  7,  9, 11, 13, 14, 15, 63,
 +         7,  7, 11, 12, 14, 15, 63, 63,
 +         9, 11, 13, 14, 15, 63, 63, 63,
 +        11, 11, 13, 14, 63, 63, 63, 63,
 +        11, 13, 14, 63, 63, 63, 63, 63,
 +        13, 14, 63, 63, 63, 63, 63, 63,
 +        13, 63, 63, 63, 63, 63, 63, 63,
 +        63, 63, 63, 63, 63, 63, 63, 63
 +    }, {
 +         4,  5,  6,  7,  9, 11, 13, 15,
 +         5,  5,  7,  8, 11, 13, 15, 17,
 +         6,  7,  9, 11, 13, 15, 15, 17,
 +         7,  7,  9, 11, 13, 15, 17, 19,
 +         7,  9, 11, 13, 14, 16, 19, 23,
 +         9, 11, 13, 14, 16, 19, 23, 29,
 +         9, 11, 13, 15, 17, 21, 28, 35,
 +        11, 13, 16, 17, 21, 28, 35, 41
 +    }, {
 +         4,  4,  5,  5,  6,  7,  7,  9,
 +         4,  4,  5,  6,  7,  7,  9,  9,
 +         5,  5,  6,  7,  7,  9,  9, 10,
 +         5,  5,  6,  7,  7,  9,  9, 10,
 +         5,  6,  7,  7,  8,  9, 10, 12,
 +         6,  7,  7,  8,  9, 10, 12, 15,
 +         6,  7,  7,  9, 10, 11, 14, 17,
 +         7,  7,  9, 10, 11, 14, 17, 21
 +    }, {
 +         4,  4,  4,  4,  4,  4,  4,  4,
 +         4,  4,  4,  4,  4,  4,  4,  4,
 +         4,  4,  4,  4,  4,  4,  4,  4,
 +         4,  4,  4,  4,  4,  4,  4,  5,
 +         4,  4,  4,  4,  4,  4,  5,  5,
 +         4,  4,  4,  4,  4,  5,  5,  6,
 +         4,  4,  4,  4,  5,  5,  6,  7,
 +         4,  4,  4,  4,  5,  6,  7,  7
 +    }
 +};
 +
 +static const uint8_t QMAT_CHROMA[4][64] = {
 +    {
 +         4,  7,  9, 11, 13, 14, 63, 63,
 +         7,  7, 11, 12, 14, 63, 63, 63,
 +         9, 11, 13, 14, 63, 63, 63, 63,
 +        11, 11, 13, 14, 63, 63, 63, 63,
 +        11, 13, 14, 63, 63, 63, 63, 63,
 +        13, 14, 63, 63, 63, 63, 63, 63,
 +        13, 63, 63, 63, 63, 63, 63, 63,
 +        63, 63, 63, 63, 63, 63, 63, 63
 +    }, {
 +         4,  5,  6,  7,  9, 11, 13, 15,
 +         5,  5,  7,  8, 11, 13, 15, 17,
 +         6,  7,  9, 11, 13, 15, 15, 17,
 +         7,  7,  9, 11, 13, 15, 17, 19,
 +         7,  9, 11, 13, 14, 16, 19, 23,
 +         9, 11, 13, 14, 16, 19, 23, 29,
 +         9, 11, 13, 15, 17, 21, 28, 35,
 +        11, 13, 16, 17, 21, 28, 35, 41
 +    }, {
 +         4,  4,  5,  5,  6,  7,  7,  9,
 +         4,  4,  5,  6,  7,  7,  9,  9,
 +         5,  5,  6,  7,  7,  9,  9, 10,
 +         5,  5,  6,  7,  7,  9,  9, 10,
 +         5,  6,  7,  7,  8,  9, 10, 12,
 +         6,  7,  7,  8,  9, 10, 12, 15,
 +         6,  7,  7,  9, 10, 11, 14, 17,
 +         7,  7,  9, 10, 11, 14, 17, 21
 +    }, {
 +         4,  4,  4,  4,  4,  4,  4,  4,
 +         4,  4,  4,  4,  4,  4,  4,  4,
 +         4,  4,  4,  4,  4,  4,  4,  4,
 +         4,  4,  4,  4,  4,  4,  4,  5,
 +         4,  4,  4,  4,  4,  4,  5,  5,
 +         4,  4,  4,  4,  4,  5,  5,  6,
 +         4,  4,  4,  4,  5,  5,  6,  7,
 +         4,  4,  4,  4,  5,  6,  7,  7
 +    }
 +};
 +
 +
 +typedef struct {
 +    uint8_t* fill_y;
 +    uint8_t* fill_u;
 +    uint8_t* fill_v;
 +
 +    int qmat_luma[16][64];
 +    int qmat_chroma[16][64];
 +} ProresContext;
 +
 +static void encode_codeword(PutBitContext *pb, int val, int codebook)
 +{
 +    unsigned int rice_order, exp_order, switch_bits, first_exp, exp, zeros,
 +            mask;
 +
 +    /* number of bits to switch between rice and exp golomb */
 +    switch_bits = codebook & 3;
 +    rice_order  = codebook >> 5;
 +    exp_order   = (codebook >> 2) & 7;
 +
 +    first_exp = ((switch_bits + 1) << rice_order);
 +
 +    if (val >= first_exp) { /* exp golomb */
 +        val -= first_exp;
 +        val += (1 << exp_order);
 +        exp = av_log2(val);
 +        zeros = exp - exp_order + switch_bits + 1;
 +        put_bits(pb, zeros, 0);
 +        put_bits(pb, exp + 1, val);
 +    } else if (rice_order) {
 +        mask = (1 << rice_order) - 1;
 +        put_bits(pb, (val >> rice_order), 0);
 +        put_bits(pb, 1, 1);
 +        put_bits(pb, rice_order, val & mask);
 +    } else {
 +        put_bits(pb, val, 0);
 +        put_bits(pb, 1, 1);
 +    }
 +}
 +
 +#define QSCALE(qmat,ind,val) ((val) / (qmat[ind]))
 +#define TO_GOLOMB(val) ((val << 1) ^ (val >> 31))
 +#define DIFF_SIGN(val, sign) ((val >> 31) ^ sign)
 +#define IS_NEGATIVE(val) (((val >> 31) ^ -1) + 1)
 +#define TO_GOLOMB2(val,sign) (val==0 ? 0 : (val << 1) + sign)
 +
 +static av_always_inline int get_level(int val)
 +{
 +    int sign = (val >> 31);
 +    return (val ^ sign) - sign;
 +}
 +
 +#define FIRST_DC_CB 0xB8
 +
 +static const uint8_t dc_codebook[7] = { 0x04, 0x28, 0x28, 0x4D, 0x4D, 0x70, 0x70};
 +
-         DCTELEM *in, int blocks_per_slice, int *qmat)
++static void encode_dc_coeffs(PutBitContext *pb, int16_t *in,
 +        int blocks_per_slice, int *qmat)
 +{
 +    int prev_dc, code;
 +    int i, sign, idx;
 +    int new_dc, delta, diff_sign, new_code;
 +
 +    prev_dc = QSCALE(qmat, 0, in[0] - 16384);
 +    code = TO_GOLOMB(prev_dc);
 +    encode_codeword(pb, code, FIRST_DC_CB);
 +
 +    code = 5; sign = 0; idx = 64;
 +    for (i = 1; i < blocks_per_slice; i++, idx += 64) {
 +        new_dc    = QSCALE(qmat, 0, in[idx] - 16384);
 +        delta     = new_dc - prev_dc;
 +        diff_sign = DIFF_SIGN(delta, sign);
 +        new_code  = TO_GOLOMB2(get_level(delta), diff_sign);
 +
 +        encode_codeword(pb, new_code, dc_codebook[FFMIN(code, 6)]);
 +
 +        code      = new_code;
 +        sign      = delta >> 31;
 +        prev_dc   = new_dc;
 +    }
 +}
 +
 +static const uint8_t run_to_cb[16] = { 0x06, 0x06, 0x05, 0x05, 0x04, 0x29,
 +        0x29, 0x29, 0x29, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x4C };
 +static const uint8_t lev_to_cb[10] = { 0x04, 0x0A, 0x05, 0x06, 0x04, 0x28,
 +        0x28, 0x28, 0x28, 0x4C };
 +
 +static void encode_ac_coeffs(AVCodecContext *avctx, PutBitContext *pb,
- static void get(uint8_t *pixels, int stride, DCTELEM* block)
++        int16_t *in, int blocks_per_slice, int *qmat)
 +{
 +    int prev_run = 4;
 +    int prev_level = 2;
 +
 +    int run = 0, level, code, i, j;
 +    for (i = 1; i < 64; i++) {
 +        int indp = progressive_scan[i];
 +        for (j = 0; j < blocks_per_slice; j++) {
 +            int val = QSCALE(qmat, indp, in[(j << 6) + indp]);
 +            if (val) {
 +                encode_codeword(pb, run, run_to_cb[FFMIN(prev_run, 15)]);
 +
 +                prev_run   = run;
 +                run        = 0;
 +                level      = get_level(val);
 +                code       = level - 1;
 +
 +                encode_codeword(pb, code, lev_to_cb[FFMIN(prev_level, 9)]);
 +
 +                prev_level = level;
 +
 +                put_bits(pb, 1, IS_NEGATIVE(val));
 +            } else {
 +                ++run;
 +            }
 +        }
 +    }
 +}
 +
- static void fdct_get(uint8_t *pixels, int stride, DCTELEM* block)
++static void get(uint8_t *pixels, int stride, int16_t* block)
 +{
 +    int16_t *p = (int16_t*)pixels;
 +    int i, j;
 +
 +    stride >>= 1;
 +    for (i = 0; i < 8; i++) {
 +        for (j = 0; j < 8; j++) {
 +            block[j] = p[j];
 +        }
 +        p += stride;
 +        block += 8;
 +    }
 +}
 +
-     DECLARE_ALIGNED(16, DCTELEM, blocks)[DEFAULT_SLICE_MB_WIDTH << 8], *block;
++static void fdct_get(uint8_t *pixels, int stride, int16_t* block)
 +{
 +    get(pixels, stride, block);
 +    ff_jpeg_fdct_islow_10(block);
 +}
 +
 +static int encode_slice_plane(AVCodecContext *avctx, int mb_count,
 +        uint8_t *src, int src_stride, uint8_t *buf, unsigned buf_size,
 +        int *qmat, int chroma)
 +{
++    DECLARE_ALIGNED(16, int16_t, blocks)[DEFAULT_SLICE_MB_WIDTH << 8], *block;
 +    int i, blocks_per_slice;
 +    PutBitContext pb;
 +
 +    block = blocks;
 +    for (i = 0; i < mb_count; i++) {
 +        fdct_get(src,                  src_stride, block + (0 << 6));
 +        fdct_get(src + 8 * src_stride, src_stride, block + ((2 - chroma) << 6));
 +        if (!chroma) {
 +            fdct_get(src + 16,                  src_stride, block + (1 << 6));
 +            fdct_get(src + 16 + 8 * src_stride, src_stride, block + (3 << 6));
 +        }
 +
 +        block += (256 >> chroma);
 +        src   += (32  >> chroma);
 +    }
 +
 +    blocks_per_slice = mb_count << (2 - chroma);
 +    init_put_bits(&pb, buf, buf_size << 3);
 +
 +    encode_dc_coeffs(&pb, blocks, blocks_per_slice, qmat);
 +    encode_ac_coeffs(avctx, &pb, blocks, blocks_per_slice, qmat);
 +
 +    flush_put_bits(&pb);
 +    return put_bits_ptr(&pb) - pb.buf;
 +}
 +
 +static av_always_inline unsigned encode_slice_data(AVCodecContext *avctx,
 +        uint8_t *dest_y, uint8_t *dest_u, uint8_t *dest_v, int luma_stride,
 +        int chroma_stride, unsigned mb_count, uint8_t *buf, unsigned data_size,
 +        unsigned* y_data_size, unsigned* u_data_size, unsigned* v_data_size,
 +        int qp)
 +{
 +    ProresContext* ctx = avctx->priv_data;
 +
 +    *y_data_size = encode_slice_plane(avctx, mb_count, dest_y, luma_stride,
 +            buf, data_size, ctx->qmat_luma[qp - 1], 0);
 +
 +    if (!(avctx->flags & CODEC_FLAG_GRAY)) {
 +        *u_data_size = encode_slice_plane(avctx, mb_count, dest_u,
 +                chroma_stride, buf + *y_data_size, data_size - *y_data_size,
 +                ctx->qmat_chroma[qp - 1], 1);
 +
 +        *v_data_size = encode_slice_plane(avctx, mb_count, dest_v,
 +                chroma_stride, buf + *y_data_size + *u_data_size,
 +                data_size - *y_data_size - *u_data_size,
 +                ctx->qmat_chroma[qp - 1], 1);
 +    }
 +
 +    return *y_data_size + *u_data_size + *v_data_size;
 +}
 +
 +static void subimage_with_fill(uint16_t *src, unsigned x, unsigned y,
 +        unsigned stride, unsigned width, unsigned height, uint16_t *dst,
 +        unsigned dst_width, unsigned dst_height)
 +{
 +
 +    int box_width = FFMIN(width - x, dst_width);
 +    int box_height = FFMIN(height - y, dst_height);
 +    int i, j, src_stride = stride >> 1;
 +    uint16_t last_pix, *last_line;
 +
 +    src += y * src_stride + x;
 +    for (i = 0; i < box_height; ++i) {
 +        for (j = 0; j < box_width; ++j) {
 +            dst[j] = src[j];
 +        }
 +        last_pix = dst[j - 1];
 +        for (; j < dst_width; j++)
 +            dst[j] = last_pix;
 +        src += src_stride;
 +        dst += dst_width;
 +    }
 +    last_line = dst - dst_width;
 +    for (; i < dst_height; i++) {
 +        for (j = 0; j < dst_width; ++j) {
 +            dst[j] = last_line[j];
 +        }
 +        dst += dst_width;
 +    }
 +}
 +
 +static int encode_slice(AVCodecContext *avctx, const AVFrame *pic, int mb_x,
 +        int mb_y, unsigned mb_count, uint8_t *buf, unsigned data_size,
 +        int unsafe, int *qp)
 +{
 +    int luma_stride, chroma_stride;
 +    int hdr_size = 6, slice_size;
 +    uint8_t *dest_y, *dest_u, *dest_v;
 +    unsigned y_data_size = 0, u_data_size = 0, v_data_size = 0;
 +    ProresContext* ctx = avctx->priv_data;
 +    int tgt_bits   = (mb_count * bitrate_table[avctx->profile]) >> 2;
 +    int low_bytes  = (tgt_bits - (tgt_bits >> 3)) >> 3; // 12% bitrate fluctuation
 +    int high_bytes = (tgt_bits + (tgt_bits >> 3)) >> 3;
 +
 +    luma_stride   = pic->linesize[0];
 +    chroma_stride = pic->linesize[1];
 +
 +    dest_y = pic->data[0] + (mb_y << 4) * luma_stride   + (mb_x << 5);
 +    dest_u = pic->data[1] + (mb_y << 4) * chroma_stride + (mb_x << 4);
 +    dest_v = pic->data[2] + (mb_y << 4) * chroma_stride + (mb_x << 4);
 +
 +    if (unsafe) {
 +
 +        subimage_with_fill((uint16_t *) pic->data[0], mb_x << 4, mb_y << 4,
 +                luma_stride, avctx->width, avctx->height,
 +                (uint16_t *) ctx->fill_y, mb_count << 4, 16);
 +        subimage_with_fill((uint16_t *) pic->data[1], mb_x << 3, mb_y << 4,
 +                chroma_stride, avctx->width >> 1, avctx->height,
 +                (uint16_t *) ctx->fill_u, mb_count << 3, 16);
 +        subimage_with_fill((uint16_t *) pic->data[2], mb_x << 3, mb_y << 4,
 +                chroma_stride, avctx->width >> 1, avctx->height,
 +                (uint16_t *) ctx->fill_v, mb_count << 3, 16);
 +
 +        encode_slice_data(avctx, ctx->fill_y, ctx->fill_u, ctx->fill_v,
 +                mb_count << 5, mb_count << 4, mb_count, buf + hdr_size,
 +                data_size - hdr_size, &y_data_size, &u_data_size, &v_data_size,
 +                *qp);
 +    } else {
 +        slice_size = encode_slice_data(avctx, dest_y, dest_u, dest_v,
 +                luma_stride, chroma_stride, mb_count, buf + hdr_size,
 +                data_size - hdr_size, &y_data_size, &u_data_size, &v_data_size,
 +                *qp);
 +
 +        if (slice_size > high_bytes && *qp < qp_end_table[avctx->profile]) {
 +            do {
 +                *qp += 1;
 +                slice_size = encode_slice_data(avctx, dest_y, dest_u, dest_v,
 +                        luma_stride, chroma_stride, mb_count, buf + hdr_size,
 +                        data_size - hdr_size, &y_data_size, &u_data_size,
 +                        &v_data_size, *qp);
 +            } while (slice_size > high_bytes && *qp < qp_end_table[avctx->profile]);
 +        } else if (slice_size < low_bytes && *qp
 +                > qp_start_table[avctx->profile]) {
 +            do {
 +                *qp -= 1;
 +                slice_size = encode_slice_data(avctx, dest_y, dest_u, dest_v,
 +                        luma_stride, chroma_stride, mb_count, buf + hdr_size,
 +                        data_size - hdr_size, &y_data_size, &u_data_size,
 +                        &v_data_size, *qp);
 +            } while (slice_size < low_bytes && *qp > qp_start_table[avctx->profile]);
 +        }
 +    }
 +
 +    buf[0] = hdr_size << 3;
 +    buf[1] = *qp;
 +    AV_WB16(buf + 2, y_data_size);
 +    AV_WB16(buf + 4, u_data_size);
 +
 +    return hdr_size + y_data_size + u_data_size + v_data_size;
 +}
 +
 +static int prores_encode_picture(AVCodecContext *avctx, const AVFrame *pic,
 +        uint8_t *buf, const int buf_size)
 +{
 +    int mb_width = (avctx->width + 15) >> 4;
 +    int mb_height = (avctx->height + 15) >> 4;
 +    int hdr_size, sl_size, i;
 +    int mb_y, sl_data_size, qp;
 +    int unsafe_bot, unsafe_right;
 +    uint8_t *sl_data, *sl_data_sizes;
 +    int slice_per_line = 0, rem = mb_width;
 +
 +    for (i = av_log2(DEFAULT_SLICE_MB_WIDTH); i >= 0; --i) {
 +        slice_per_line += rem >> i;
 +        rem &= (1 << i) - 1;
 +    }
 +
 +    qp = qp_start_table[avctx->profile];
 +    hdr_size = 8; sl_data_size = buf_size - hdr_size;
 +    sl_data_sizes = buf + hdr_size;
 +    sl_data = sl_data_sizes + (slice_per_line * mb_height * 2);
 +    for (mb_y = 0; mb_y < mb_height; mb_y++) {
 +        int mb_x = 0;
 +        int slice_mb_count = DEFAULT_SLICE_MB_WIDTH;
 +        while (mb_x < mb_width) {
 +            while (mb_width - mb_x < slice_mb_count)
 +                slice_mb_count >>= 1;
 +
 +            unsafe_bot = (avctx->height & 0xf) && (mb_y == mb_height - 1);
 +            unsafe_right = (avctx->width & 0xf) && (mb_x + slice_mb_count == mb_width);
 +
 +            sl_size = encode_slice(avctx, pic, mb_x, mb_y, slice_mb_count,
 +                    sl_data, sl_data_size, unsafe_bot || unsafe_right, &qp);
 +
 +            bytestream_put_be16(&sl_data_sizes, sl_size);
 +            sl_data           += sl_size;
 +            sl_data_size      -= sl_size;
 +            mb_x              += slice_mb_count;
 +        }
 +    }
 +
 +    buf[0] = hdr_size << 3;
 +    AV_WB32(buf + 1, sl_data - buf);
 +    AV_WB16(buf + 5, slice_per_line * mb_height);
 +    buf[7] = av_log2(DEFAULT_SLICE_MB_WIDTH) << 4;
 +
 +    return sl_data - buf;
 +}
 +
 +static int prores_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
 +                               const AVFrame *pict, int *got_packet)
 +{
 +    int header_size = 148;
 +    uint8_t *buf;
 +    int pic_size, ret;
 +    int frame_size = FFALIGN(avctx->width, 16) * FFALIGN(avctx->height, 16)*16 + 500 + FF_MIN_BUFFER_SIZE; //FIXME choose tighter limit
 +
 +
 +    if ((ret = ff_alloc_packet2(avctx, pkt, frame_size + FF_MIN_BUFFER_SIZE)) < 0)
 +        return ret;
 +
 +    buf = pkt->data;
 +    pic_size = prores_encode_picture(avctx, pict, buf + header_size + 8,
 +            pkt->size - header_size - 8);
 +
 +    bytestream_put_be32(&buf, pic_size + 8 + header_size);
 +    bytestream_put_buffer(&buf, "icpf", 4);
 +
 +    bytestream_put_be16(&buf, header_size);
 +    bytestream_put_be16(&buf, 0);
 +    bytestream_put_buffer(&buf, "fmpg", 4);
 +    bytestream_put_be16(&buf, avctx->width);
 +    bytestream_put_be16(&buf, avctx->height);
 +    *buf++ = 0x83; // {10}(422){00}{00}(frame){11}
 +    *buf++ = 0;
 +    *buf++ = 2;
 +    *buf++ = 2;
 +    *buf++ = 6;
 +    *buf++ = 32;
 +    *buf++ = 0;
 +    *buf++ = 3;
 +
 +    bytestream_put_buffer(&buf, QMAT_LUMA[avctx->profile],   64);
 +    bytestream_put_buffer(&buf, QMAT_CHROMA[avctx->profile], 64);
 +
 +    pkt->flags |= AV_PKT_FLAG_KEY;
 +    pkt->size = pic_size + 8 + header_size;
 +    *got_packet = 1;
 +
 +    return 0;
 +}
 +
 +static void scale_mat(const uint8_t* src, int* dst, int scale)
 +{
 +    int i;
 +    for (i = 0; i < 64; i++)
 +        dst[i] = src[i] * scale;
 +}
 +
 +static av_cold int prores_encode_init(AVCodecContext *avctx)
 +{
 +    int i;
 +    ProresContext* ctx = avctx->priv_data;
 +
 +    if (avctx->pix_fmt != AV_PIX_FMT_YUV422P10) {
 +        av_log(avctx, AV_LOG_ERROR, "need YUV422P10\n");
 +        return -1;
 +    }
 +    if (avctx->width & 0x1) {
 +        av_log(avctx, AV_LOG_ERROR,
 +                "frame width needs to be multiple of 2\n");
 +        return -1;
 +    }
 +
 +    if ((avctx->height & 0xf) || (avctx->width & 0xf)) {
 +        ctx->fill_y = av_malloc(4 * (DEFAULT_SLICE_MB_WIDTH << 8));
 +        if (!ctx->fill_y)
 +            return AVERROR(ENOMEM);
 +        ctx->fill_u = ctx->fill_y + (DEFAULT_SLICE_MB_WIDTH << 9);
 +        ctx->fill_v = ctx->fill_u + (DEFAULT_SLICE_MB_WIDTH << 8);
 +    }
 +
 +    if (avctx->profile == FF_PROFILE_UNKNOWN) {
 +        avctx->profile = FF_PROFILE_PRORES_STANDARD;
 +        av_log(avctx, AV_LOG_INFO,
 +                "encoding with ProRes standard (apcn) profile\n");
 +
 +    } else if (avctx->profile < FF_PROFILE_PRORES_PROXY
 +            || avctx->profile > FF_PROFILE_PRORES_HQ) {
 +        av_log(
 +                avctx,
 +                AV_LOG_ERROR,
 +                "unknown profile %d, use [0 - apco, 1 - apcs, 2 - apcn (default), 3 - apch]\n",
 +                avctx->profile);
 +        return -1;
 +    }
 +
 +    avctx->codec_tag = AV_RL32((const uint8_t*)profiles[avctx->profile].name);
 +
 +    for (i = 1; i <= 16; i++) {
 +        scale_mat(QMAT_LUMA[avctx->profile]  , ctx->qmat_luma[i - 1]  , i);
 +        scale_mat(QMAT_CHROMA[avctx->profile], ctx->qmat_chroma[i - 1], i);
 +    }
 +
 +    avctx->coded_frame = avcodec_alloc_frame();
 +    avctx->coded_frame->key_frame = 1;
 +    avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I;
 +
 +    return 0;
 +}
 +
 +static av_cold int prores_encode_close(AVCodecContext *avctx)
 +{
 +    ProresContext* ctx = avctx->priv_data;
 +    av_freep(&avctx->coded_frame);
 +    av_freep(&ctx->fill_y);
 +
 +    return 0;
 +}
 +
 +AVCodec ff_prores_anatoliy_encoder = {
 +    .name           = "prores_anatoliy",
 +    .type           = AVMEDIA_TYPE_VIDEO,
 +    .id             = AV_CODEC_ID_PRORES,
 +    .priv_data_size = sizeof(ProresContext),
 +    .init           = prores_encode_init,
 +    .close          = prores_encode_close,
 +    .encode2        = prores_encode_frame,
 +    .pix_fmts       = (const enum AVPixelFormat[]){AV_PIX_FMT_YUV422P10, AV_PIX_FMT_NONE},
 +    .long_name      = NULL_IF_CONFIG_SMALL("Apple ProRes"),
 +    .capabilities   = CODEC_CAP_FRAME_THREADS | CODEC_CAP_INTRA_ONLY,
 +    .profiles       = profiles
 +};
 +
 +AVCodec ff_prores_encoder = {
 +    .name           = "prores",
 +    .type           = AVMEDIA_TYPE_VIDEO,
 +    .id             = AV_CODEC_ID_PRORES,
 +    .priv_data_size = sizeof(ProresContext),
 +    .init           = prores_encode_init,
 +    .close          = prores_encode_close,
 +    .encode2        = prores_encode_frame,
 +    .pix_fmts       = (const enum AVPixelFormat[]){AV_PIX_FMT_YUV422P10, AV_PIX_FMT_NONE},
 +    .long_name      = NULL_IF_CONFIG_SMALL("Apple ProRes"),
 +    .capabilities   = CODEC_CAP_FRAME_THREADS | CODEC_CAP_INTRA_ONLY,
 +    .profiles       = profiles
 +};
index 0462c74,0000000..8da13ac
mode 100644,000000..100644
--- /dev/null
@@@ -1,1076 -1,0 +1,1077 @@@
-     DECLARE_ALIGNED(16, DCTELEM, blocks)[MAX_PLANES][64 * 4 * MAX_MBS_PER_SLICE];
 +/*
 + * Apple ProRes encoder
 + *
 + * Copyright (c) 2012 Konstantin Shishkov
 + *
 + * This encoder appears to be based on Anatoliy Wassermans considering
 + * similarities in the bugs.
 + *
 + * This file is part of Libav.
 + *
 + * Libav is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU Lesser General Public
 + * License as published by the Free Software Foundation; either
 + * version 2.1 of the License, or (at your option) any later version.
 + *
 + * Libav is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * Lesser General Public License for more details.
 + *
 + * You should have received a copy of the GNU Lesser General Public
 + * License along with Libav; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
 +#include "libavutil/opt.h"
 +#include "avcodec.h"
++#include "dsputil.h"
 +#include "put_bits.h"
 +#include "bytestream.h"
 +#include "internal.h"
 +#include "proresdsp.h"
 +#include "proresdata.h"
 +
 +#define CFACTOR_Y422 2
 +#define CFACTOR_Y444 3
 +
 +#define MAX_MBS_PER_SLICE 8
 +
 +#define MAX_PLANES 3 // should be increased to 4 when there's AV_PIX_FMT_YUV444AP10
 +
 +enum {
 +    PRORES_PROFILE_PROXY = 0,
 +    PRORES_PROFILE_LT,
 +    PRORES_PROFILE_STANDARD,
 +    PRORES_PROFILE_HQ,
 +};
 +
 +enum {
 +    QUANT_MAT_PROXY = 0,
 +    QUANT_MAT_LT,
 +    QUANT_MAT_STANDARD,
 +    QUANT_MAT_HQ,
 +    QUANT_MAT_DEFAULT,
 +};
 +
 +static const uint8_t prores_quant_matrices[][64] = {
 +    { // proxy
 +         4,  7,  9, 11, 13, 14, 15, 63,
 +         7,  7, 11, 12, 14, 15, 63, 63,
 +         9, 11, 13, 14, 15, 63, 63, 63,
 +        11, 11, 13, 14, 63, 63, 63, 63,
 +        11, 13, 14, 63, 63, 63, 63, 63,
 +        13, 14, 63, 63, 63, 63, 63, 63,
 +        13, 63, 63, 63, 63, 63, 63, 63,
 +        63, 63, 63, 63, 63, 63, 63, 63,
 +    },
 +    { // LT
 +         4,  5,  6,  7,  9, 11, 13, 15,
 +         5,  5,  7,  8, 11, 13, 15, 17,
 +         6,  7,  9, 11, 13, 15, 15, 17,
 +         7,  7,  9, 11, 13, 15, 17, 19,
 +         7,  9, 11, 13, 14, 16, 19, 23,
 +         9, 11, 13, 14, 16, 19, 23, 29,
 +         9, 11, 13, 15, 17, 21, 28, 35,
 +        11, 13, 16, 17, 21, 28, 35, 41,
 +    },
 +    { // standard
 +         4,  4,  5,  5,  6,  7,  7,  9,
 +         4,  4,  5,  6,  7,  7,  9,  9,
 +         5,  5,  6,  7,  7,  9,  9, 10,
 +         5,  5,  6,  7,  7,  9,  9, 10,
 +         5,  6,  7,  7,  8,  9, 10, 12,
 +         6,  7,  7,  8,  9, 10, 12, 15,
 +         6,  7,  7,  9, 10, 11, 14, 17,
 +         7,  7,  9, 10, 11, 14, 17, 21,
 +    },
 +    { // high quality
 +         4,  4,  4,  4,  4,  4,  4,  4,
 +         4,  4,  4,  4,  4,  4,  4,  4,
 +         4,  4,  4,  4,  4,  4,  4,  4,
 +         4,  4,  4,  4,  4,  4,  4,  5,
 +         4,  4,  4,  4,  4,  4,  5,  5,
 +         4,  4,  4,  4,  4,  5,  5,  6,
 +         4,  4,  4,  4,  5,  5,  6,  7,
 +         4,  4,  4,  4,  5,  6,  7,  7,
 +    },
 +    { // codec default
 +         4,  4,  4,  4,  4,  4,  4,  4,
 +         4,  4,  4,  4,  4,  4,  4,  4,
 +         4,  4,  4,  4,  4,  4,  4,  4,
 +         4,  4,  4,  4,  4,  4,  4,  4,
 +         4,  4,  4,  4,  4,  4,  4,  4,
 +         4,  4,  4,  4,  4,  4,  4,  4,
 +         4,  4,  4,  4,  4,  4,  4,  4,
 +         4,  4,  4,  4,  4,  4,  4,  4,
 +    },
 +};
 +
 +#define NUM_MB_LIMITS 4
 +static const int prores_mb_limits[NUM_MB_LIMITS] = {
 +    1620, // up to 720x576
 +    2700, // up to 960x720
 +    6075, // up to 1440x1080
 +    9216, // up to 2048x1152
 +};
 +
 +static const struct prores_profile {
 +    const char *full_name;
 +    uint32_t    tag;
 +    int         min_quant;
 +    int         max_quant;
 +    int         br_tab[NUM_MB_LIMITS];
 +    int         quant;
 +} prores_profile_info[4] = {
 +    {
 +        .full_name = "proxy",
 +        .tag       = MKTAG('a', 'p', 'c', 'o'),
 +        .min_quant = 4,
 +        .max_quant = 8,
 +        .br_tab    = { 300, 242, 220, 194 },
 +        .quant     = QUANT_MAT_PROXY,
 +    },
 +    {
 +        .full_name = "LT",
 +        .tag       = MKTAG('a', 'p', 'c', 's'),
 +        .min_quant = 1,
 +        .max_quant = 9,
 +        .br_tab    = { 720, 560, 490, 440 },
 +        .quant     = QUANT_MAT_LT,
 +    },
 +    {
 +        .full_name = "standard",
 +        .tag       = MKTAG('a', 'p', 'c', 'n'),
 +        .min_quant = 1,
 +        .max_quant = 6,
 +        .br_tab    = { 1050, 808, 710, 632 },
 +        .quant     = QUANT_MAT_STANDARD,
 +    },
 +    {
 +        .full_name = "high quality",
 +        .tag       = MKTAG('a', 'p', 'c', 'h'),
 +        .min_quant = 1,
 +        .max_quant = 6,
 +        .br_tab    = { 1566, 1216, 1070, 950 },
 +        .quant     = QUANT_MAT_HQ,
 +    }
 +// for 4444 profile bitrate numbers are { 2350, 1828, 1600, 1425 }
 +};
 +
 +#define TRELLIS_WIDTH 16
 +#define SCORE_LIMIT   INT_MAX / 2
 +
 +struct TrellisNode {
 +    int prev_node;
 +    int quant;
 +    int bits;
 +    int score;
 +};
 +
 +#define MAX_STORED_Q 16
 +
 +typedef struct ProresThreadData {
-     DECLARE_ALIGNED(16, DCTELEM, blocks)[MAX_PLANES][64 * 4 * MAX_MBS_PER_SLICE];
++    DECLARE_ALIGNED(16, int16_t, blocks)[MAX_PLANES][64 * 4 * MAX_MBS_PER_SLICE];
 +    DECLARE_ALIGNED(16, uint16_t, emu_buf)[16 * 16];
 +    int16_t custom_q[64];
 +    struct TrellisNode *nodes;
 +} ProresThreadData;
 +
 +typedef struct ProresContext {
 +    AVClass *class;
-                            DCTELEM *blocks, uint16_t *emu_buf,
++    DECLARE_ALIGNED(16, int16_t, blocks)[MAX_PLANES][64 * 4 * MAX_MBS_PER_SLICE];
 +    DECLARE_ALIGNED(16, uint16_t, emu_buf)[16*16];
 +    int16_t quants[MAX_STORED_Q][64];
 +    int16_t custom_q[64];
 +    const uint8_t *quant_mat;
 +
 +    ProresDSPContext dsp;
 +    ScanTable  scantable;
 +
 +    int mb_width, mb_height;
 +    int mbs_per_slice;
 +    int num_chroma_blocks, chroma_factor;
 +    int slices_width;
 +    int slices_per_picture;
 +    int pictures_per_frame; // 1 for progressive, 2 for interlaced
 +    int cur_picture_idx;
 +    int num_planes;
 +    int bits_per_mb;
 +    int force_quant;
 +
 +    char *vendor;
 +    int quant_sel;
 +
 +    int frame_size_upper_bound;
 +
 +    int profile;
 +    const struct prores_profile *profile_info;
 +
 +    int *slice_q;
 +
 +    ProresThreadData *tdata;
 +} ProresContext;
 +
 +static void get_slice_data(ProresContext *ctx, const uint16_t *src,
 +                           int linesize, int x, int y, int w, int h,
- static void encode_dcs(PutBitContext *pb, DCTELEM *blocks,
++                           int16_t *blocks, uint16_t *emu_buf,
 +                           int mbs_per_slice, int blocks_per_mb, int is_chroma)
 +{
 +    const uint16_t *esrc;
 +    const int mb_width = 4 * blocks_per_mb;
 +    int elinesize;
 +    int i, j, k;
 +
 +    for (i = 0; i < mbs_per_slice; i++, src += mb_width) {
 +        if (x >= w) {
 +            memset(blocks, 0, 64 * (mbs_per_slice - i) * blocks_per_mb
 +                              * sizeof(*blocks));
 +            return;
 +        }
 +        if (x + mb_width <= w && y + 16 <= h) {
 +            esrc      = src;
 +            elinesize = linesize;
 +        } else {
 +            int bw, bh, pix;
 +
 +            esrc      = emu_buf;
 +            elinesize = 16 * sizeof(*emu_buf);
 +
 +            bw = FFMIN(w - x, mb_width);
 +            bh = FFMIN(h - y, 16);
 +
 +            for (j = 0; j < bh; j++) {
 +                memcpy(emu_buf + j * 16,
 +                       (const uint8_t*)src + j * linesize,
 +                       bw * sizeof(*src));
 +                pix = emu_buf[j * 16 + bw - 1];
 +                for (k = bw; k < mb_width; k++)
 +                    emu_buf[j * 16 + k] = pix;
 +            }
 +            for (; j < 16; j++)
 +                memcpy(emu_buf + j * 16,
 +                       emu_buf + (bh - 1) * 16,
 +                       mb_width * sizeof(*emu_buf));
 +        }
 +        if (!is_chroma) {
 +            ctx->dsp.fdct(esrc, elinesize, blocks);
 +            blocks += 64;
 +            if (blocks_per_mb > 2) {
 +                ctx->dsp.fdct(esrc + 8, elinesize, blocks);
 +                blocks += 64;
 +            }
 +            ctx->dsp.fdct(esrc + elinesize * 4, elinesize, blocks);
 +            blocks += 64;
 +            if (blocks_per_mb > 2) {
 +                ctx->dsp.fdct(esrc + elinesize * 4 + 8, elinesize, blocks);
 +                blocks += 64;
 +            }
 +        } else {
 +            ctx->dsp.fdct(esrc, elinesize, blocks);
 +            blocks += 64;
 +            ctx->dsp.fdct(esrc + elinesize * 4, elinesize, blocks);
 +            blocks += 64;
 +            if (blocks_per_mb > 2) {
 +                ctx->dsp.fdct(esrc + 8, elinesize, blocks);
 +                blocks += 64;
 +                ctx->dsp.fdct(esrc + elinesize * 4 + 8, elinesize, blocks);
 +                blocks += 64;
 +            }
 +        }
 +
 +        x += mb_width;
 +    }
 +}
 +
 +/**
 + * Write an unsigned rice/exp golomb codeword.
 + */
 +static inline void encode_vlc_codeword(PutBitContext *pb, unsigned codebook, int val)
 +{
 +    unsigned int rice_order, exp_order, switch_bits, switch_val;
 +    int exponent;
 +
 +    /* number of prefix bits to switch between Rice and expGolomb */
 +    switch_bits = (codebook & 3) + 1;
 +    rice_order  =  codebook >> 5;       /* rice code order */
 +    exp_order   = (codebook >> 2) & 7;  /* exp golomb code order */
 +
 +    switch_val  = switch_bits << rice_order;
 +
 +    if (val >= switch_val) {
 +        val -= switch_val - (1 << exp_order);
 +        exponent = av_log2(val);
 +
 +        put_bits(pb, exponent - exp_order + switch_bits, 0);
 +        put_bits(pb, exponent + 1, val);
 +    } else {
 +        exponent = val >> rice_order;
 +
 +        if (exponent)
 +            put_bits(pb, exponent, 0);
 +        put_bits(pb, 1, 1);
 +        if (rice_order)
 +            put_sbits(pb, rice_order, val);
 +    }
 +}
 +
 +#define GET_SIGN(x)  ((x) >> 31)
 +#define MAKE_CODE(x) (((x) << 1) ^ GET_SIGN(x))
 +
- static void encode_acs(PutBitContext *pb, DCTELEM *blocks,
++static void encode_dcs(PutBitContext *pb, int16_t *blocks,
 +                       int blocks_per_slice, int scale)
 +{
 +    int i;
 +    int codebook = 3, code, dc, prev_dc, delta, sign, new_sign;
 +
 +    prev_dc = (blocks[0] - 0x4000) / scale;
 +    encode_vlc_codeword(pb, FIRST_DC_CB, MAKE_CODE(prev_dc));
 +    sign     = 0;
 +    codebook = 3;
 +    blocks  += 64;
 +
 +    for (i = 1; i < blocks_per_slice; i++, blocks += 64) {
 +        dc       = (blocks[0] - 0x4000) / scale;
 +        delta    = dc - prev_dc;
 +        new_sign = GET_SIGN(delta);
 +        delta    = (delta ^ sign) - sign;
 +        code     = MAKE_CODE(delta);
 +        encode_vlc_codeword(pb, ff_prores_dc_codebook[codebook], code);
 +        codebook = (code + (code & 1)) >> 1;
 +        codebook = FFMIN(codebook, 3);
 +        sign     = new_sign;
 +        prev_dc  = dc;
 +    }
 +}
 +
-                               int mbs_per_slice, DCTELEM *blocks,
++static void encode_acs(PutBitContext *pb, int16_t *blocks,
 +                       int blocks_per_slice,
 +                       int plane_size_factor,
 +                       const uint8_t *scan, const int16_t *qmat)
 +{
 +    int idx, i;
 +    int run, level, run_cb, lev_cb;
 +    int max_coeffs, abs_level;
 +
 +    max_coeffs = blocks_per_slice << 6;
 +    run_cb     = ff_prores_run_to_cb_index[4];
 +    lev_cb     = ff_prores_lev_to_cb_index[2];
 +    run        = 0;
 +
 +    for (i = 1; i < 64; i++) {
 +        for (idx = scan[i]; idx < max_coeffs; idx += 64) {
 +            level = blocks[idx] / qmat[scan[i]];
 +            if (level) {
 +                abs_level = FFABS(level);
 +                encode_vlc_codeword(pb, ff_prores_ac_codebook[run_cb], run);
 +                encode_vlc_codeword(pb, ff_prores_ac_codebook[lev_cb],
 +                                    abs_level - 1);
 +                put_sbits(pb, 1, GET_SIGN(level));
 +
 +                run_cb = ff_prores_run_to_cb_index[FFMIN(run, 15)];
 +                lev_cb = ff_prores_lev_to_cb_index[FFMIN(abs_level, 9)];
 +                run    = 0;
 +            } else {
 +                run++;
 +            }
 +        }
 +    }
 +}
 +
 +static int encode_slice_plane(ProresContext *ctx, PutBitContext *pb,
 +                              const uint16_t *src, int linesize,
- static int estimate_dcs(int *error, DCTELEM *blocks, int blocks_per_slice,
++                              int mbs_per_slice, int16_t *blocks,
 +                              int blocks_per_mb, int plane_size_factor,
 +                              const int16_t *qmat)
 +{
 +    int blocks_per_slice, saved_pos;
 +
 +    saved_pos = put_bits_count(pb);
 +    blocks_per_slice = mbs_per_slice * blocks_per_mb;
 +
 +    encode_dcs(pb, blocks, blocks_per_slice, qmat[0]);
 +    encode_acs(pb, blocks, blocks_per_slice, plane_size_factor,
 +               ctx->scantable.permutated, qmat);
 +    flush_put_bits(pb);
 +
 +    return (put_bits_count(pb) - saved_pos) >> 3;
 +}
 +
 +static int encode_slice(AVCodecContext *avctx, const AVFrame *pic,
 +                        PutBitContext *pb,
 +                        int sizes[4], int x, int y, int quant,
 +                        int mbs_per_slice)
 +{
 +    ProresContext *ctx = avctx->priv_data;
 +    int i, xp, yp;
 +    int total_size = 0;
 +    const uint16_t *src;
 +    int slice_width_factor = av_log2(mbs_per_slice);
 +    int num_cblocks, pwidth, linesize, line_add;
 +    int plane_factor, is_chroma;
 +    uint16_t *qmat;
 +
 +    if (ctx->pictures_per_frame == 1)
 +        line_add = 0;
 +    else
 +        line_add = ctx->cur_picture_idx ^ !pic->top_field_first;
 +
 +    if (ctx->force_quant) {
 +        qmat = ctx->quants[0];
 +    } else if (quant < MAX_STORED_Q) {
 +        qmat = ctx->quants[quant];
 +    } else {
 +        qmat = ctx->custom_q;
 +        for (i = 0; i < 64; i++)
 +            qmat[i] = ctx->quant_mat[i] * quant;
 +    }
 +
 +    for (i = 0; i < ctx->num_planes; i++) {
 +        is_chroma    = (i == 1 || i == 2);
 +        plane_factor = slice_width_factor + 2;
 +        if (is_chroma)
 +            plane_factor += ctx->chroma_factor - 3;
 +        if (!is_chroma || ctx->chroma_factor == CFACTOR_Y444) {
 +            xp          = x << 4;
 +            yp          = y << 4;
 +            num_cblocks = 4;
 +            pwidth      = avctx->width;
 +        } else {
 +            xp          = x << 3;
 +            yp          = y << 4;
 +            num_cblocks = 2;
 +            pwidth      = avctx->width >> 1;
 +        }
 +
 +        linesize = pic->linesize[i] * ctx->pictures_per_frame;
 +        src = (const uint16_t*)(pic->data[i] + yp * linesize +
 +                                line_add * pic->linesize[i]) + xp;
 +
 +        get_slice_data(ctx, src, linesize, xp, yp,
 +                       pwidth, avctx->height / ctx->pictures_per_frame,
 +                       ctx->blocks[0], ctx->emu_buf,
 +                       mbs_per_slice, num_cblocks, is_chroma);
 +        sizes[i] = encode_slice_plane(ctx, pb, src, linesize,
 +                                      mbs_per_slice, ctx->blocks[0],
 +                                      num_cblocks, plane_factor,
 +                                      qmat);
 +        total_size += sizes[i];
 +    }
 +    return total_size;
 +}
 +
 +static inline int estimate_vlc(unsigned codebook, int val)
 +{
 +    unsigned int rice_order, exp_order, switch_bits, switch_val;
 +    int exponent;
 +
 +    /* number of prefix bits to switch between Rice and expGolomb */
 +    switch_bits = (codebook & 3) + 1;
 +    rice_order  =  codebook >> 5;       /* rice code order */
 +    exp_order   = (codebook >> 2) & 7;  /* exp golomb code order */
 +
 +    switch_val  = switch_bits << rice_order;
 +
 +    if (val >= switch_val) {
 +        val -= switch_val - (1 << exp_order);
 +        exponent = av_log2(val);
 +
 +        return exponent * 2 - exp_order + switch_bits + 1;
 +    } else {
 +        return (val >> rice_order) + rice_order + 1;
 +    }
 +}
 +
- static int estimate_acs(int *error, DCTELEM *blocks, int blocks_per_slice,
++static int estimate_dcs(int *error, int16_t *blocks, int blocks_per_slice,
 +                        int scale)
 +{
 +    int i;
 +    int codebook = 3, code, dc, prev_dc, delta, sign, new_sign;
 +    int bits;
 +
 +    prev_dc  = (blocks[0] - 0x4000) / scale;
 +    bits     = estimate_vlc(FIRST_DC_CB, MAKE_CODE(prev_dc));
 +    sign     = 0;
 +    codebook = 3;
 +    blocks  += 64;
 +    *error  += FFABS(blocks[0] - 0x4000) % scale;
 +
 +    for (i = 1; i < blocks_per_slice; i++, blocks += 64) {
 +        dc       = (blocks[0] - 0x4000) / scale;
 +        *error  += FFABS(blocks[0] - 0x4000) % scale;
 +        delta    = dc - prev_dc;
 +        new_sign = GET_SIGN(delta);
 +        delta    = (delta ^ sign) - sign;
 +        code     = MAKE_CODE(delta);
 +        bits    += estimate_vlc(ff_prores_dc_codebook[codebook], code);
 +        codebook = (code + (code & 1)) >> 1;
 +        codebook = FFMIN(codebook, 3);
 +        sign     = new_sign;
 +        prev_dc  = dc;
 +    }
 +
 +    return bits;
 +}
 +
++static int estimate_acs(int *error, int16_t *blocks, int blocks_per_slice,
 +                        int plane_size_factor,
 +                        const uint8_t *scan, const int16_t *qmat)
 +{
 +    int idx, i;
 +    int run, level, run_cb, lev_cb;
 +    int max_coeffs, abs_level;
 +    int bits = 0;
 +
 +    max_coeffs = blocks_per_slice << 6;
 +    run_cb     = ff_prores_run_to_cb_index[4];
 +    lev_cb     = ff_prores_lev_to_cb_index[2];
 +    run        = 0;
 +
 +    for (i = 1; i < 64; i++) {
 +        for (idx = scan[i]; idx < max_coeffs; idx += 64) {
 +            level   = blocks[idx] / qmat[scan[i]];
 +            *error += FFABS(blocks[idx]) % qmat[scan[i]];
 +            if (level) {
 +                abs_level = FFABS(level);
 +                bits += estimate_vlc(ff_prores_ac_codebook[run_cb], run);
 +                bits += estimate_vlc(ff_prores_ac_codebook[lev_cb],
 +                                     abs_level - 1) + 1;
 +
 +                run_cb = ff_prores_run_to_cb_index[FFMIN(run, 15)];
 +                lev_cb = ff_prores_lev_to_cb_index[FFMIN(abs_level, 9)];
 +                run    = 0;
 +            } else {
 +                run++;
 +            }
 +        }
 +    }
 +
 +    return bits;
 +}
 +
 +static int estimate_slice_plane(ProresContext *ctx, int *error, int plane,
 +                                const uint16_t *src, int linesize,
 +                                int mbs_per_slice,
 +                                int blocks_per_mb, int plane_size_factor,
 +                                const int16_t *qmat, ProresThreadData *td)
 +{
 +    int blocks_per_slice;
 +    int bits;
 +
 +    blocks_per_slice = mbs_per_slice * blocks_per_mb;
 +
 +    bits  = estimate_dcs(error, td->blocks[plane], blocks_per_slice, qmat[0]);
 +    bits += estimate_acs(error, td->blocks[plane], blocks_per_slice,
 +                         plane_size_factor, ctx->scantable.permutated, qmat);
 +
 +    return FFALIGN(bits, 8);
 +}
 +
 +static int find_slice_quant(AVCodecContext *avctx, const AVFrame *pic,
 +                            int trellis_node, int x, int y, int mbs_per_slice,
 +                            ProresThreadData *td)
 +{
 +    ProresContext *ctx = avctx->priv_data;
 +    int i, q, pq, xp, yp;
 +    const uint16_t *src;
 +    int slice_width_factor = av_log2(mbs_per_slice);
 +    int num_cblocks[MAX_PLANES], pwidth;
 +    int plane_factor[MAX_PLANES], is_chroma[MAX_PLANES];
 +    const int min_quant = ctx->profile_info->min_quant;
 +    const int max_quant = ctx->profile_info->max_quant;
 +    int error, bits, bits_limit;
 +    int mbs, prev, cur, new_score;
 +    int slice_bits[TRELLIS_WIDTH], slice_score[TRELLIS_WIDTH];
 +    int overquant;
 +    uint16_t *qmat;
 +    int linesize[4], line_add;
 +
 +    if (ctx->pictures_per_frame == 1)
 +        line_add = 0;
 +    else
 +        line_add = ctx->cur_picture_idx ^ !pic->top_field_first;
 +    mbs = x + mbs_per_slice;
 +
 +    for (i = 0; i < ctx->num_planes; i++) {
 +        is_chroma[i]    = (i == 1 || i == 2);
 +        plane_factor[i] = slice_width_factor + 2;
 +        if (is_chroma[i])
 +            plane_factor[i] += ctx->chroma_factor - 3;
 +        if (!is_chroma[i] || ctx->chroma_factor == CFACTOR_Y444) {
 +            xp             = x << 4;
 +            yp             = y << 4;
 +            num_cblocks[i] = 4;
 +            pwidth         = avctx->width;
 +        } else {
 +            xp             = x << 3;
 +            yp             = y << 4;
 +            num_cblocks[i] = 2;
 +            pwidth         = avctx->width >> 1;
 +        }
 +
 +        linesize[i] = pic->linesize[i] * ctx->pictures_per_frame;
 +        src = (const uint16_t*)(pic->data[i] + yp * linesize[i] +
 +                                line_add * pic->linesize[i]) + xp;
 +
 +        get_slice_data(ctx, src, linesize[i], xp, yp,
 +                       pwidth, avctx->height / ctx->pictures_per_frame,
 +                       td->blocks[i], td->emu_buf,
 +                       mbs_per_slice, num_cblocks[i], is_chroma[i]);
 +    }
 +
 +    for (q = min_quant; q < max_quant + 2; q++) {
 +        td->nodes[trellis_node + q].prev_node = -1;
 +        td->nodes[trellis_node + q].quant     = q;
 +    }
 +
 +    // todo: maybe perform coarser quantising to fit into frame size when needed
 +    for (q = min_quant; q <= max_quant; q++) {
 +        bits  = 0;
 +        error = 0;
 +        for (i = 0; i < ctx->num_planes; i++) {
 +            bits += estimate_slice_plane(ctx, &error, i,
 +                                         src, linesize[i],
 +                                         mbs_per_slice,
 +                                         num_cblocks[i], plane_factor[i],
 +                                         ctx->quants[q], td);
 +        }
 +        if (bits > 65000 * 8) {
 +            error = SCORE_LIMIT;
 +            break;
 +        }
 +        slice_bits[q]  = bits;
 +        slice_score[q] = error;
 +    }
 +    if (slice_bits[max_quant] <= ctx->bits_per_mb * mbs_per_slice) {
 +        slice_bits[max_quant + 1]  = slice_bits[max_quant];
 +        slice_score[max_quant + 1] = slice_score[max_quant] + 1;
 +        overquant = max_quant;
 +    } else {
 +        for (q = max_quant + 1; q < 128; q++) {
 +            bits  = 0;
 +            error = 0;
 +            if (q < MAX_STORED_Q) {
 +                qmat = ctx->quants[q];
 +            } else {
 +                qmat = td->custom_q;
 +                for (i = 0; i < 64; i++)
 +                    qmat[i] = ctx->quant_mat[i] * q;
 +            }
 +            for (i = 0; i < ctx->num_planes; i++) {
 +                bits += estimate_slice_plane(ctx, &error, i,
 +                                             src, linesize[i],
 +                                             mbs_per_slice,
 +                                             num_cblocks[i], plane_factor[i],
 +                                             qmat, td);
 +            }
 +            if (bits <= ctx->bits_per_mb * mbs_per_slice)
 +                break;
 +        }
 +
 +        slice_bits[max_quant + 1]  = bits;
 +        slice_score[max_quant + 1] = error;
 +        overquant = q;
 +    }
 +    td->nodes[trellis_node + max_quant + 1].quant = overquant;
 +
 +    bits_limit = mbs * ctx->bits_per_mb;
 +    for (pq = min_quant; pq < max_quant + 2; pq++) {
 +        prev = trellis_node - TRELLIS_WIDTH + pq;
 +
 +        for (q = min_quant; q < max_quant + 2; q++) {
 +            cur = trellis_node + q;
 +
 +            bits  = td->nodes[prev].bits + slice_bits[q];
 +            error = slice_score[q];
 +            if (bits > bits_limit)
 +                error = SCORE_LIMIT;
 +
 +            if (td->nodes[prev].score < SCORE_LIMIT && error < SCORE_LIMIT)
 +                new_score = td->nodes[prev].score + error;
 +            else
 +                new_score = SCORE_LIMIT;
 +            if (td->nodes[cur].prev_node == -1 ||
 +                td->nodes[cur].score >= new_score) {
 +
 +                td->nodes[cur].bits      = bits;
 +                td->nodes[cur].score     = new_score;
 +                td->nodes[cur].prev_node = prev;
 +            }
 +        }
 +    }
 +
 +    error = td->nodes[trellis_node + min_quant].score;
 +    pq    = trellis_node + min_quant;
 +    for (q = min_quant + 1; q < max_quant + 2; q++) {
 +        if (td->nodes[trellis_node + q].score <= error) {
 +            error = td->nodes[trellis_node + q].score;
 +            pq    = trellis_node + q;
 +        }
 +    }
 +
 +    return pq;
 +}
 +
 +static int find_quant_thread(AVCodecContext *avctx, void *arg,
 +                             int jobnr, int threadnr)
 +{
 +    ProresContext *ctx = avctx->priv_data;
 +    ProresThreadData *td = ctx->tdata + threadnr;
 +    int mbs_per_slice = ctx->mbs_per_slice;
 +    int x, y = jobnr, mb, q = 0;
 +
 +    for (x = mb = 0; x < ctx->mb_width; x += mbs_per_slice, mb++) {
 +        while (ctx->mb_width - x < mbs_per_slice)
 +            mbs_per_slice >>= 1;
 +        q = find_slice_quant(avctx, avctx->coded_frame,
 +                             (mb + 1) * TRELLIS_WIDTH, x, y,
 +                             mbs_per_slice, td);
 +    }
 +
 +    for (x = ctx->slices_width - 1; x >= 0; x--) {
 +        ctx->slice_q[x + y * ctx->slices_width] = td->nodes[q].quant;
 +        q = td->nodes[q].prev_node;
 +    }
 +
 +    return 0;
 +}
 +
 +static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
 +                        const AVFrame *pic, int *got_packet)
 +{
 +    ProresContext *ctx = avctx->priv_data;
 +    uint8_t *orig_buf, *buf, *slice_hdr, *slice_sizes, *tmp;
 +    uint8_t *picture_size_pos;
 +    PutBitContext pb;
 +    int x, y, i, mb, q = 0;
 +    int sizes[4] = { 0 };
 +    int slice_hdr_size = 2 + 2 * (ctx->num_planes - 1);
 +    int frame_size, picture_size, slice_size;
 +    int pkt_size, ret;
 +    uint8_t frame_flags;
 +
 +    *avctx->coded_frame           = *pic;
 +    avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I;
 +    avctx->coded_frame->key_frame = 1;
 +
 +    pkt_size = ctx->frame_size_upper_bound + FF_MIN_BUFFER_SIZE;
 +
 +    if ((ret = ff_alloc_packet2(avctx, pkt, pkt_size)) < 0)
 +        return ret;
 +
 +    orig_buf = pkt->data;
 +
 +    // frame atom
 +    orig_buf += 4;                              // frame size
 +    bytestream_put_be32  (&orig_buf, FRAME_ID); // frame container ID
 +    buf = orig_buf;
 +
 +    // frame header
 +    tmp = buf;
 +    buf += 2;                                   // frame header size will be stored here
 +    bytestream_put_be16  (&buf, 0);             // version 1
 +    bytestream_put_buffer(&buf, ctx->vendor, 4);
 +    bytestream_put_be16  (&buf, avctx->width);
 +    bytestream_put_be16  (&buf, avctx->height);
 +
 +    frame_flags = ctx->chroma_factor << 6;
 +    if (avctx->flags & CODEC_FLAG_INTERLACED_DCT)
 +        frame_flags |= pic->top_field_first ? 0x04 : 0x08;
 +    bytestream_put_byte  (&buf, frame_flags);
 +
 +    bytestream_put_byte  (&buf, 0);             // reserved
 +    bytestream_put_byte  (&buf, avctx->color_primaries);
 +    bytestream_put_byte  (&buf, avctx->color_trc);
 +    bytestream_put_byte  (&buf, avctx->colorspace);
 +    bytestream_put_byte  (&buf, 0x40);          // source format and alpha information
 +    bytestream_put_byte  (&buf, 0);             // reserved
 +    if (ctx->quant_sel != QUANT_MAT_DEFAULT) {
 +        bytestream_put_byte  (&buf, 0x03);      // matrix flags - both matrices are present
 +        // luma quantisation matrix
 +        for (i = 0; i < 64; i++)
 +            bytestream_put_byte(&buf, ctx->quant_mat[i]);
 +        // chroma quantisation matrix
 +        for (i = 0; i < 64; i++)
 +            bytestream_put_byte(&buf, ctx->quant_mat[i]);
 +    } else {
 +        bytestream_put_byte  (&buf, 0x00);      // matrix flags - default matrices are used
 +    }
 +    bytestream_put_be16  (&tmp, buf - orig_buf); // write back frame header size
 +
 +    for (ctx->cur_picture_idx = 0;
 +         ctx->cur_picture_idx < ctx->pictures_per_frame;
 +         ctx->cur_picture_idx++) {
 +        // picture header
 +        picture_size_pos = buf + 1;
 +        bytestream_put_byte  (&buf, 0x40);          // picture header size (in bits)
 +        buf += 4;                                   // picture data size will be stored here
 +        bytestream_put_be16  (&buf, ctx->slices_per_picture);
 +        bytestream_put_byte  (&buf, av_log2(ctx->mbs_per_slice) << 4); // slice width and height in MBs
 +
 +        // seek table - will be filled during slice encoding
 +        slice_sizes = buf;
 +        buf += ctx->slices_per_picture * 2;
 +
 +        // slices
 +        if (!ctx->force_quant) {
 +            ret = avctx->execute2(avctx, find_quant_thread, NULL, NULL,
 +                                  ctx->mb_height);
 +            if (ret)
 +                return ret;
 +        }
 +
 +        for (y = 0; y < ctx->mb_height; y++) {
 +            int mbs_per_slice = ctx->mbs_per_slice;
 +            for (x = mb = 0; x < ctx->mb_width; x += mbs_per_slice, mb++) {
 +                q = ctx->force_quant ? ctx->force_quant
 +                                     : ctx->slice_q[mb + y * ctx->slices_width];
 +
 +                while (ctx->mb_width - x < mbs_per_slice)
 +                    mbs_per_slice >>= 1;
 +
 +                bytestream_put_byte(&buf, slice_hdr_size << 3);
 +                slice_hdr = buf;
 +                buf += slice_hdr_size - 1;
 +                init_put_bits(&pb, buf, (pkt_size - (buf - orig_buf)) * 8);
 +                encode_slice(avctx, pic, &pb, sizes, x, y, q, mbs_per_slice);
 +
 +                bytestream_put_byte(&slice_hdr, q);
 +                slice_size = slice_hdr_size + sizes[ctx->num_planes - 1];
 +                for (i = 0; i < ctx->num_planes - 1; i++) {
 +                    bytestream_put_be16(&slice_hdr, sizes[i]);
 +                    slice_size += sizes[i];
 +                }
 +                bytestream_put_be16(&slice_sizes, slice_size);
 +                buf += slice_size - slice_hdr_size;
 +            }
 +        }
 +
 +        picture_size = buf - (picture_size_pos - 1);
 +        bytestream_put_be32(&picture_size_pos, picture_size);
 +    }
 +
 +    orig_buf -= 8;
 +    frame_size = buf - orig_buf;
 +    bytestream_put_be32(&orig_buf, frame_size);
 +
 +    pkt->size   = frame_size;
 +    pkt->flags |= AV_PKT_FLAG_KEY;
 +    *got_packet = 1;
 +
 +    return 0;
 +}
 +
 +static av_cold int encode_close(AVCodecContext *avctx)
 +{
 +    ProresContext *ctx = avctx->priv_data;
 +    int i;
 +
 +    av_freep(&avctx->coded_frame);
 +
 +    if (ctx->tdata) {
 +        for (i = 0; i < avctx->thread_count; i++)
 +            av_free(ctx->tdata[i].nodes);
 +    }
 +    av_freep(&ctx->tdata);
 +    av_freep(&ctx->slice_q);
 +
 +    return 0;
 +}
 +
 +static av_cold int encode_init(AVCodecContext *avctx)
 +{
 +    ProresContext *ctx = avctx->priv_data;
 +    int mps;
 +    int i, j;
 +    int min_quant, max_quant;
 +    int interlaced = !!(avctx->flags & CODEC_FLAG_INTERLACED_DCT);
 +
 +    avctx->bits_per_raw_sample = 10;
 +    avctx->coded_frame = avcodec_alloc_frame();
 +    if (!avctx->coded_frame)
 +        return AVERROR(ENOMEM);
 +
 +    ff_proresdsp_init(&ctx->dsp, avctx);
 +    ff_init_scantable(ctx->dsp.dct_permutation, &ctx->scantable,
 +                      interlaced ? ff_prores_interlaced_scan
 +                                 : ff_prores_progressive_scan);
 +
 +    mps = ctx->mbs_per_slice;
 +    if (mps & (mps - 1)) {
 +        av_log(avctx, AV_LOG_ERROR,
 +               "there should be an integer power of two MBs per slice\n");
 +        return AVERROR(EINVAL);
 +    }
 +
 +    ctx->chroma_factor = avctx->pix_fmt == AV_PIX_FMT_YUV422P10
 +                         ? CFACTOR_Y422
 +                         : CFACTOR_Y444;
 +    ctx->profile_info  = prores_profile_info + ctx->profile;
 +    ctx->num_planes    = 3;
 +
 +    ctx->mb_width      = FFALIGN(avctx->width,  16) >> 4;
 +
 +    if (interlaced)
 +        ctx->mb_height = FFALIGN(avctx->height, 32) >> 5;
 +    else
 +        ctx->mb_height = FFALIGN(avctx->height, 16) >> 4;
 +
 +    ctx->slices_width  = ctx->mb_width / mps;
 +    ctx->slices_width += av_popcount(ctx->mb_width - ctx->slices_width * mps);
 +    ctx->slices_per_picture = ctx->mb_height * ctx->slices_width;
 +    ctx->pictures_per_frame = 1 + interlaced;
 +
 +    if (ctx->quant_sel == -1)
 +        ctx->quant_mat = prores_quant_matrices[ctx->profile_info->quant];
 +    else
 +        ctx->quant_mat = prores_quant_matrices[ctx->quant_sel];
 +
 +    if (strlen(ctx->vendor) != 4) {
 +        av_log(avctx, AV_LOG_ERROR, "vendor ID should be 4 bytes\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    ctx->force_quant = avctx->global_quality / FF_QP2LAMBDA;
 +    if (!ctx->force_quant) {
 +        if (!ctx->bits_per_mb) {
 +            for (i = 0; i < NUM_MB_LIMITS - 1; i++)
 +                if (prores_mb_limits[i] >= ctx->mb_width * ctx->mb_height *
 +                                           ctx->pictures_per_frame)
 +                    break;
 +            ctx->bits_per_mb   = ctx->profile_info->br_tab[i];
 +        } else if (ctx->bits_per_mb < 128) {
 +            av_log(avctx, AV_LOG_ERROR, "too few bits per MB, please set at least 128\n");
 +            return AVERROR_INVALIDDATA;
 +        }
 +
 +        min_quant = ctx->profile_info->min_quant;
 +        max_quant = ctx->profile_info->max_quant;
 +        for (i = min_quant; i < MAX_STORED_Q; i++) {
 +            for (j = 0; j < 64; j++)
 +                ctx->quants[i][j] = ctx->quant_mat[j] * i;
 +        }
 +
 +        ctx->slice_q = av_malloc(ctx->slices_per_picture * sizeof(*ctx->slice_q));
 +        if (!ctx->slice_q) {
 +            encode_close(avctx);
 +            return AVERROR(ENOMEM);
 +        }
 +
 +        ctx->tdata = av_mallocz(avctx->thread_count * sizeof(*ctx->tdata));
 +        if (!ctx->tdata) {
 +            encode_close(avctx);
 +            return AVERROR(ENOMEM);
 +        }
 +
 +        for (j = 0; j < avctx->thread_count; j++) {
 +            ctx->tdata[j].nodes = av_malloc((ctx->slices_width + 1)
 +                                            * TRELLIS_WIDTH
 +                                            * sizeof(*ctx->tdata->nodes));
 +            if (!ctx->tdata[j].nodes) {
 +                encode_close(avctx);
 +                return AVERROR(ENOMEM);
 +            }
 +            for (i = min_quant; i < max_quant + 2; i++) {
 +                ctx->tdata[j].nodes[i].prev_node = -1;
 +                ctx->tdata[j].nodes[i].bits      = 0;
 +                ctx->tdata[j].nodes[i].score     = 0;
 +            }
 +        }
 +    } else {
 +        int ls = 0;
 +
 +        if (ctx->force_quant > 64) {
 +            av_log(avctx, AV_LOG_ERROR, "too large quantiser, maximum is 64\n");
 +            return AVERROR_INVALIDDATA;
 +        }
 +
 +        for (j = 0; j < 64; j++) {
 +            ctx->quants[0][j] = ctx->quant_mat[j] * ctx->force_quant;
 +            ls += av_log2((1 << 11)  / ctx->quants[0][j]) * 2 + 1;
 +        }
 +
 +        ctx->bits_per_mb = ls * 8;
 +        if (ctx->chroma_factor == CFACTOR_Y444)
 +            ctx->bits_per_mb += ls * 4;
 +        if (ctx->num_planes == 4)
 +            ctx->bits_per_mb += ls * 4;
 +    }
 +
 +    ctx->frame_size_upper_bound = ctx->pictures_per_frame *
 +                                  ctx->slices_per_picture *
 +                                  (2 + 2 * ctx->num_planes +
 +                                   (mps * ctx->bits_per_mb) / 8)
 +                                  + 200;
 +
 +    avctx->codec_tag   = ctx->profile_info->tag;
 +
 +    av_log(avctx, AV_LOG_DEBUG,
 +           "profile %d, %d slices, interlacing: %s, %d bits per MB\n",
 +           ctx->profile, ctx->slices_per_picture * ctx->pictures_per_frame,
 +           interlaced ? "yes" : "no", ctx->bits_per_mb);
 +    av_log(avctx, AV_LOG_DEBUG, "frame size upper bound: %d\n",
 +           ctx->frame_size_upper_bound);
 +
 +    return 0;
 +}
 +
 +#define OFFSET(x) offsetof(ProresContext, x)
 +#define VE     AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
 +
 +static const AVOption options[] = {
 +    { "mbs_per_slice", "macroblocks per slice", OFFSET(mbs_per_slice),
 +        AV_OPT_TYPE_INT, { .i64 = 8 }, 1, MAX_MBS_PER_SLICE, VE },
 +    { "profile",       NULL, OFFSET(profile), AV_OPT_TYPE_INT,
 +        { .i64 = PRORES_PROFILE_STANDARD },
 +        PRORES_PROFILE_PROXY, PRORES_PROFILE_HQ, VE, "profile" },
 +    { "proxy",         NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PRORES_PROFILE_PROXY },
 +        0, 0, VE, "profile" },
 +    { "lt",            NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PRORES_PROFILE_LT },
 +        0, 0, VE, "profile" },
 +    { "standard",      NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PRORES_PROFILE_STANDARD },
 +        0, 0, VE, "profile" },
 +    { "hq",            NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PRORES_PROFILE_HQ },
 +        0, 0, VE, "profile" },
 +    { "vendor", "vendor ID", OFFSET(vendor),
 +        AV_OPT_TYPE_STRING, { .str = "Lavc" }, CHAR_MIN, CHAR_MAX, VE },
 +    { "bits_per_mb", "desired bits per macroblock", OFFSET(bits_per_mb),
 +        AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 8192, VE },
 +    { "quant_mat", "quantiser matrix", OFFSET(quant_sel), AV_OPT_TYPE_INT,
 +        { .i64 = -1 }, -1, QUANT_MAT_DEFAULT, VE, "quant_mat" },
 +    { "auto",          NULL, 0, AV_OPT_TYPE_CONST, { .i64 = -1 },
 +        0, 0, VE, "quant_mat" },
 +    { "proxy",         NULL, 0, AV_OPT_TYPE_CONST, { .i64 = QUANT_MAT_PROXY },
 +        0, 0, VE, "quant_mat" },
 +    { "lt",            NULL, 0, AV_OPT_TYPE_CONST, { .i64 = QUANT_MAT_LT },
 +        0, 0, VE, "quant_mat" },
 +    { "standard",      NULL, 0, AV_OPT_TYPE_CONST, { .i64 = QUANT_MAT_STANDARD },
 +        0, 0, VE, "quant_mat" },
 +    { "hq",            NULL, 0, AV_OPT_TYPE_CONST, { .i64 = QUANT_MAT_HQ },
 +        0, 0, VE, "quant_mat" },
 +    { "default",       NULL, 0, AV_OPT_TYPE_CONST, { .i64 = QUANT_MAT_DEFAULT },
 +        0, 0, VE, "quant_mat" },
 +    { NULL }
 +};
 +
 +static const AVClass proresenc_class = {
 +    .class_name = "ProRes encoder",
 +    .item_name  = av_default_item_name,
 +    .option     = options,
 +    .version    = LIBAVUTIL_VERSION_INT,
 +};
 +
 +AVCodec ff_prores_kostya_encoder = {
 +    .name           = "prores_kostya",
 +    .type           = AVMEDIA_TYPE_VIDEO,
 +    .id             = AV_CODEC_ID_PRORES,
 +    .priv_data_size = sizeof(ProresContext),
 +    .init           = encode_init,
 +    .close          = encode_close,
 +    .encode2        = encode_frame,
 +    .capabilities   = CODEC_CAP_SLICE_THREADS,
 +    .long_name      = NULL_IF_CONFIG_SMALL("Apple ProRes (iCodec Pro)"),
 +    .pix_fmts       = (const enum AVPixelFormat[]) {
 +                          AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10, AV_PIX_FMT_NONE
 +                      },
 +    .priv_class     = &proresenc_class,
 +};
Simple merge
Simple merge
@@@ -215,9 -214,9 +215,9 @@@ static int rv34_decode_cbp(GetBitContex
  }
  
  /**
 - * Get one coefficient value from the bistream and store it.
 + * Get one coefficient value from the bitstream and store it.
   */
- static inline void decode_coeff(DCTELEM *dst, int coef, int esc, GetBitContext *gb, VLC* vlc, int q)
+ static inline void decode_coeff(int16_t *dst, int coef, int esc, GetBitContext *gb, VLC* vlc, int q)
  {
      if(coef){
          if(coef == esc){
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -1836,80 -1769,6 +1836,80 @@@ void ff_avg_vc1_mspel_mc00_mmxext(uint8
      avg_pixels8_mmxext(dst, src, stride, 8);
  }
  
-                                     DCTELEM *block)
 +#if CONFIG_DIRAC_DECODER
 +#define DIRAC_PIXOP(OPNAME, EXT)\
 +void ff_ ## OPNAME ## _dirac_pixels8_ ## EXT(uint8_t *dst, const uint8_t *src[5], int stride, int h)\
 +{\
 +    OPNAME ## _pixels8_ ## EXT(dst, src[0], stride, h);\
 +}\
 +void ff_ ## OPNAME ## _dirac_pixels16_ ## EXT(uint8_t *dst, const uint8_t *src[5], int stride, int h)\
 +{\
 +    OPNAME ## _pixels16_ ## EXT(dst, src[0], stride, h);\
 +}\
 +void ff_ ## OPNAME ## _dirac_pixels32_ ## EXT(uint8_t *dst, const uint8_t *src[5], int stride, int h)\
 +{\
 +    OPNAME ## _pixels16_ ## EXT(dst   , src[0]   , stride, h);\
 +    OPNAME ## _pixels16_ ## EXT(dst+16, src[0]+16, stride, h);\
 +}
 +
 +DIRAC_PIXOP(put, mmx)
 +DIRAC_PIXOP(avg, mmx)
 +DIRAC_PIXOP(avg, mmxext)
 +
 +#if HAVE_YASM
 +void ff_put_dirac_pixels16_sse2(uint8_t *dst, const uint8_t *src[5], int stride, int h)
 +{
 +    ff_put_pixels16_sse2(dst, src[0], stride, h);
 +}
 +void ff_avg_dirac_pixels16_sse2(uint8_t *dst, const uint8_t *src[5], int stride, int h)
 +{
 +    ff_avg_pixels16_sse2(dst, src[0], stride, h);
 +}
 +void ff_put_dirac_pixels32_sse2(uint8_t *dst, const uint8_t *src[5], int stride, int h)
 +{
 +    ff_put_pixels16_sse2(dst   , src[0]   , stride, h);
 +    ff_put_pixels16_sse2(dst+16, src[0]+16, stride, h);
 +}
 +void ff_avg_dirac_pixels32_sse2(uint8_t *dst, const uint8_t *src[5], int stride, int h)
 +{
 +    ff_avg_pixels16_sse2(dst   , src[0]   , stride, h);
 +    ff_avg_pixels16_sse2(dst+16, src[0]+16, stride, h);
 +}
 +#endif
 +#endif
 +
 +/* XXX: Those functions should be suppressed ASAP when all IDCTs are
 + * converted. */
 +#if CONFIG_GPL
 +static void ff_libmpeg2mmx_idct_put(uint8_t *dest, int line_size,
-                                     DCTELEM *block)
++                                    int16_t *block)
 +{
 +    ff_mmx_idct(block);
 +    ff_put_pixels_clamped_mmx(block, dest, line_size);
 +}
 +
 +static void ff_libmpeg2mmx_idct_add(uint8_t *dest, int line_size,
-                                      DCTELEM *block)
++                                    int16_t *block)
 +{
 +    ff_mmx_idct(block);
 +    ff_add_pixels_clamped_mmx(block, dest, line_size);
 +}
 +
 +static void ff_libmpeg2mmx2_idct_put(uint8_t *dest, int line_size,
-                                      DCTELEM *block)
++                                     int16_t *block)
 +{
 +    ff_mmxext_idct(block);
 +    ff_put_pixels_clamped_mmx(block, dest, line_size);
 +}
 +
 +static void ff_libmpeg2mmx2_idct_add(uint8_t *dest, int line_size,
++                                     int16_t *block)
 +{
 +    ff_mmxext_idct(block);
 +    ff_add_pixels_clamped_mmx(block, dest, line_size);
 +}
 +#endif
 +
  static void vector_clipf_sse(float *dst, const float *src,
                               float min, float max, int len)
  {
@@@ -100,10 -100,6 +100,10 @@@ void ff_put_rv40_qpel16_mc33_mmx(uint8_
  void ff_avg_rv40_qpel8_mc33_mmx(uint8_t *block, uint8_t *pixels, int line_size);
  void ff_avg_rv40_qpel16_mc33_mmx(uint8_t *block, uint8_t *pixels, int line_size);
  
- void ff_mmx_idct(DCTELEM *block);
- void ff_mmxext_idct(DCTELEM *block);
++void ff_mmx_idct(int16_t *block);
++void ff_mmxext_idct(int16_t *block);
 +
 +
  void ff_deinterlace_line_mmx(uint8_t *dst,
                               const uint8_t *lum_m4, const uint8_t *lum_m3,
                               const uint8_t *lum_m2, const uint8_t *lum_m1,
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
  #include "libavcodec/proresdsp.h"
  
  void ff_prores_idct_put_10_sse2(uint16_t *dst, int linesize,
-                                 DCTELEM *block, const int16_t *qmat);
+                                 int16_t *block, const int16_t *qmat);
  void ff_prores_idct_put_10_sse4(uint16_t *dst, int linesize,
-                                 DCTELEM *block, const int16_t *qmat);
+                                 int16_t *block, const int16_t *qmat);
  void ff_prores_idct_put_10_avx (uint16_t *dst, int linesize,
-                                 DCTELEM *block, const int16_t *qmat);
+                                 int16_t *block, const int16_t *qmat);
  
 -void ff_proresdsp_x86_init(ProresDSPContext *dsp)
 +void ff_proresdsp_x86_init(ProresDSPContext *dsp, AVCodecContext *avctx)
  {
  #if ARCH_X86_64
      int flags = av_get_cpu_flags();
Simple merge
Simple merge
@@@ -23,8 -21,8 +23,9 @@@
  #include "libavutil/attributes.h"
  #include "libavutil/cpu.h"
  #include "libavutil/x86/cpu.h"
 +#include "libavutil/x86/asm.h"
  #include "libavcodec/avcodec.h"
+ #include "libavcodec/dsputil.h"
  #include "libavcodec/vp3dsp.h"
  #include "config.h"
  
Simple merge
Simple merge
index 6f806b2,0000000..6090c9a
mode 100644,000000..100644
--- /dev/null
@@@ -1,2117 -1,0 +1,2117 @@@
- static void column_fidct_c(int16_t* thr_adr, DCTELEM *data, DCTELEM *output, int cnt);
- static void row_idct_c(DCTELEM* workspace,
 +/*
 + * Copyright (C) 2003 Michael Niedermayer <michaelni@gmx.at>
 + * Copyright (C) 2005 Nikolaj Poroshin <porosh3@psu.ru>
 + *
 + * This file is part of MPlayer.
 + *
 + * MPlayer is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License as published by
 + * the Free Software Foundation; either version 2 of the License, or
 + * (at your option) any later version.
 + *
 + * MPlayer 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 General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License along
 + * with MPlayer; if not, write to the Free Software Foundation, Inc.,
 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 + */
 +
 +/*
 + * This implementation is based on an algorithm described in
 + * "Aria Nosratinia Embedded Post-Processing for
 + * Enhancement of Compressed Images (1999)"
 + * (http://citeseer.nj.nec.com/nosratinia99embedded.html)
 + * Futher, with splitting (i)dct into hor/ver passes, one of them can be
 + * performed once per block, not pixel. This allows for much better speed.
 + */
 +
 +/*
 +  Heavily optimized version of SPP filter by Nikolaj
 + */
 +
 +#include <stdio.h>
 +#include <stdlib.h>
 +#include <string.h>
 +#include <inttypes.h>
 +#include <math.h>
 +
 +#include "config.h"
 +
 +#include "mp_msg.h"
 +#include "cpudetect.h"
 +#include "img_format.h"
 +#include "mp_image.h"
 +#include "vf.h"
 +#include "vd_ffmpeg.h"
 +#include "libvo/fastmemcpy.h"
 +
 +#include "libavutil/internal.h"
 +#include "libavutil/intreadwrite.h"
 +#include "libavutil/mem.h"
 +#include "libavcodec/avcodec.h"
 +#include "libavcodec/dsputil.h"
 +
 +#undef free
 +#undef malloc
 +
 +//===========================================================================//
 +#define BLOCKSZ 12
 +
 +static const short custom_threshold[64]=
 +// values (296) can't be too high
 +// -it causes too big quant dependence
 +// or maybe overflow(check), which results in some flashing
 +{ 71, 296, 295, 237,  71,  40,  38,  19,
 +  245, 193, 185, 121, 102,  73,  53,  27,
 +  158, 129, 141, 107,  97,  73,  50,  26,
 +  102, 116, 109,  98,  82,  66,  45,  23,
 +  71,  94,  95,  81,  70,  56,  38,  20,
 +  56,  77,  74,  66,  56,  44,  30,  15,
 +  38,  53,  50,  45,  38,  30,  21,  11,
 +  20,  27,  26,  23,  20,  15,  11,   5
 +};
 +
 +static const uint8_t  __attribute__((aligned(32))) dither[8][8]={
 +    {  0,  48,  12,  60,   3,  51,  15,  63, },
 +    { 32,  16,  44,  28,  35,  19,  47,  31, },
 +    {  8,  56,   4,  52,  11,  59,   7,  55, },
 +    { 40,  24,  36,  20,  43,  27,  39,  23, },
 +    {  2,  50,  14,  62,   1,  49,  13,  61, },
 +    { 34,  18,  46,  30,  33,  17,  45,  29, },
 +    { 10,  58,   6,  54,   9,  57,   5,  53, },
 +    { 42,  26,  38,  22,  41,  25,  37,  21, },
 +};
 +
 +struct vf_priv_s { //align 16 !
 +    uint64_t threshold_mtx_noq[8*2];
 +    uint64_t threshold_mtx[8*2];//used in both C & MMX (& later SSE2) versions
 +
 +    int log2_count;
 +    int temp_stride;
 +    int qp;
 +    int mpeg2;
 +    int prev_q;
 +    uint8_t *src;
 +    int16_t *temp;
 +    int bframes;
 +    char *non_b_qp;
 +};
 +
 +
 +#if !HAVE_MMX
 +
 +//This func reads from 1 slice, 1 and clears 0 & 1
 +static void store_slice_c(uint8_t *dst, int16_t *src, int dst_stride, int src_stride, int width, int height, int log2_scale)
 +{int y, x;
 +#define STORE(pos)                                                        \
 +    temp= (src[x + pos] + (d[pos]>>log2_scale))>>(6-log2_scale);        \
 +    src[x + pos]=src[x + pos - 8*src_stride]=0;                                \
 +    if(temp & 0x100) temp= ~(temp>>31);                                        \
 +    dst[x + pos]= temp;
 +
 +    for(y=0; y<height; y++){
 +        const uint8_t *d= dither[y];
 +        for(x=0; x<width; x+=8){
 +            int temp;
 +            STORE(0);
 +            STORE(1);
 +            STORE(2);
 +            STORE(3);
 +            STORE(4);
 +            STORE(5);
 +            STORE(6);
 +            STORE(7);
 +        }
 +        src+=src_stride;
 +        dst+=dst_stride;
 +    }
 +}
 +
 +//This func reads from 2 slices, 0 & 2  and clears 2-nd
 +static void store_slice2_c(uint8_t *dst, int16_t *src, int dst_stride, int src_stride, int width, int height, int log2_scale)
 +{int y, x;
 +#define STORE2(pos)                                                        \
 +    temp= (src[x + pos] + src[x + pos + 16*src_stride] + (d[pos]>>log2_scale))>>(6-log2_scale);        \
 +    src[x + pos + 16*src_stride]=0;                                        \
 +    if(temp & 0x100) temp= ~(temp>>31);                                        \
 +    dst[x + pos]= temp;
 +
 +    for(y=0; y<height; y++){
 +        const uint8_t *d= dither[y];
 +        for(x=0; x<width; x+=8){
 +            int temp;
 +            STORE2(0);
 +            STORE2(1);
 +            STORE2(2);
 +            STORE2(3);
 +            STORE2(4);
 +            STORE2(5);
 +            STORE2(6);
 +            STORE2(7);
 +        }
 +        src+=src_stride;
 +        dst+=dst_stride;
 +    }
 +}
 +
 +static void mul_thrmat_c(struct vf_priv_s *p,int q)
 +{
 +    int a;
 +    for(a=0;a<64;a++)
 +        ((short*)p->threshold_mtx)[a]=q * ((short*)p->threshold_mtx_noq)[a];//ints faster in C
 +}
 +
- static void row_fdct_c(DCTELEM *data, const uint8_t *pixels, int line_size, int cnt);
++static void column_fidct_c(int16_t* thr_adr, int16_t *data, int16_t *output, int cnt);
++static void row_idct_c(int16_t* workspace,
 +                       int16_t* output_adr, int output_stride, int cnt);
- static void column_fidct_mmx(int16_t* thr_adr,  DCTELEM *data,  DCTELEM *output,  int cnt);
- static void row_idct_mmx(DCTELEM* workspace,
++static void row_fdct_c(int16_t *data, const uint8_t *pixels, int line_size, int cnt);
 +
 +//this is rather ugly, but there is no need for function pointers
 +#define store_slice_s store_slice_c
 +#define store_slice2_s store_slice2_c
 +#define mul_thrmat_s mul_thrmat_c
 +#define column_fidct_s column_fidct_c
 +#define row_idct_s row_idct_c
 +#define row_fdct_s row_fdct_c
 +
 +#else /* HAVE_MMX */
 +
 +//This func reads from 1 slice, 1 and clears 0 & 1
 +static void store_slice_mmx(uint8_t *dst, int16_t *src, long dst_stride, long src_stride, long width, long height, long log2_scale)
 +{
 +    const uint8_t *od=&dither[0][0];
 +    const uint8_t *end=&dither[height][0];
 +    width = (width+7)&~7;
 +    dst_stride-=width;
 +    //src_stride=(src_stride-width)*2;
 +    __asm__ volatile(
 +        "mov %5, %%"REG_d"                \n\t"
 +        "mov %6, %%"REG_S"                \n\t"
 +        "mov %7, %%"REG_D"                \n\t"
 +        "mov %1, %%"REG_a"                \n\t"
 +        "movd %%"REG_d", %%mm5             \n\t"
 +        "xor $-1, %%"REG_d"              \n\t"
 +        "mov %%"REG_a", %%"REG_c"             \n\t"
 +        "add $7, %%"REG_d"               \n\t"
 +        "neg %%"REG_a"                   \n\t"
 +        "sub %0, %%"REG_c"            \n\t"
 +        "add %%"REG_c", %%"REG_c"             \n\t"
 +        "movd %%"REG_d", %%mm2             \n\t"
 +        "mov %%"REG_c", %1       \n\t"
 +        "mov %2, %%"REG_d"               \n\t"
 +        "shl $4, %%"REG_a"               \n\t"
 +
 +        "2:                        \n\t"
 +        "movq (%%"REG_d"), %%mm3           \n\t"
 +        "movq %%mm3, %%mm4             \n\t"
 +        "pxor %%mm7, %%mm7             \n\t"
 +        "punpcklbw %%mm7, %%mm3        \n\t"
 +        "punpckhbw %%mm7, %%mm4        \n\t"
 +        "mov %0, %%"REG_c"            \n\t"
 +        "psraw %%mm5, %%mm3            \n\t"
 +        "psraw %%mm5, %%mm4            \n\t"
 +        "1:                        \n\t"
 +        "movq %%mm7, (%%"REG_S",%%"REG_a",)     \n\t"
 +        "movq (%%"REG_S"), %%mm0           \n\t"
 +        "movq 8(%%"REG_S"), %%mm1          \n\t"
 +
 +        "movq %%mm7, 8(%%"REG_S",%%"REG_a",)    \n\t"
 +        "paddw %%mm3, %%mm0            \n\t"
 +        "paddw %%mm4, %%mm1            \n\t"
 +
 +        "movq %%mm7, (%%"REG_S")           \n\t"
 +        "psraw %%mm2, %%mm0            \n\t"
 +        "psraw %%mm2, %%mm1            \n\t"
 +
 +        "movq %%mm7, 8(%%"REG_S")          \n\t"
 +        "packuswb %%mm1, %%mm0         \n\t"
 +        "add $16, %%"REG_S"              \n\t"
 +
 +        "movq %%mm0, (%%"REG_D")           \n\t"
 +        "add $8, %%"REG_D"               \n\t"
 +        "sub $8, %%"REG_c"               \n\t"
 +        "jg 1b                      \n\t"
 +        "add %1, %%"REG_S"       \n\t"
 +        "add $8, %%"REG_d"               \n\t"
 +        "add %3, %%"REG_D"       \n\t"
 +        "cmp %4, %%"REG_d"           \n\t"
 +        "jl 2b                      \n\t"
 +
 +        :
 +        : "m" (width), "m" (src_stride), "erm" (od), "m" (dst_stride), "erm" (end),
 +          "m" (log2_scale), "m" (src), "m" (dst) //input
 +        : "%"REG_a, "%"REG_c, "%"REG_d, "%"REG_S, "%"REG_D
 +        );
 +}
 +
 +//This func reads from 2 slices, 0 & 2  and clears 2-nd
 +static void store_slice2_mmx(uint8_t *dst, int16_t *src, long dst_stride, long src_stride, long width, long height, long log2_scale)
 +{
 +    const uint8_t *od=&dither[0][0];
 +    const uint8_t *end=&dither[height][0];
 +    width = (width+7)&~7;
 +    dst_stride-=width;
 +    //src_stride=(src_stride-width)*2;
 +    __asm__ volatile(
 +        "mov %5, %%"REG_d"                \n\t"
 +        "mov %6, %%"REG_S"                \n\t"
 +        "mov %7, %%"REG_D"                \n\t"
 +        "mov %1, %%"REG_a"            \n\t"
 +        "movd %%"REG_d", %%mm5             \n\t"
 +        "xor $-1, %%"REG_d"              \n\t"
 +        "mov %%"REG_a", %%"REG_c"             \n\t"
 +        "add $7, %%"REG_d"               \n\t"
 +        "sub %0, %%"REG_c"            \n\t"
 +        "add %%"REG_c", %%"REG_c"             \n\t"
 +        "movd %%"REG_d", %%mm2             \n\t"
 +        "mov %%"REG_c", %1       \n\t"
 +        "mov %2, %%"REG_d"               \n\t"
 +        "shl $5, %%"REG_a"               \n\t"
 +
 +        "2:                        \n\t"
 +        "movq (%%"REG_d"), %%mm3           \n\t"
 +        "movq %%mm3, %%mm4             \n\t"
 +        "pxor %%mm7, %%mm7             \n\t"
 +        "punpcklbw %%mm7, %%mm3        \n\t"
 +        "punpckhbw %%mm7, %%mm4        \n\t"
 +        "mov %0, %%"REG_c"            \n\t"
 +        "psraw %%mm5, %%mm3            \n\t"
 +        "psraw %%mm5, %%mm4            \n\t"
 +        "1:                        \n\t"
 +        "movq (%%"REG_S"), %%mm0           \n\t"
 +        "movq 8(%%"REG_S"), %%mm1          \n\t"
 +        "paddw %%mm3, %%mm0            \n\t"
 +
 +        "paddw (%%"REG_S",%%"REG_a",), %%mm0    \n\t"
 +        "paddw %%mm4, %%mm1            \n\t"
 +        "movq 8(%%"REG_S",%%"REG_a",), %%mm6    \n\t"
 +
 +        "movq %%mm7, (%%"REG_S",%%"REG_a",)     \n\t"
 +        "psraw %%mm2, %%mm0            \n\t"
 +        "paddw %%mm6, %%mm1            \n\t"
 +
 +        "movq %%mm7, 8(%%"REG_S",%%"REG_a",)    \n\t"
 +        "psraw %%mm2, %%mm1            \n\t"
 +        "packuswb %%mm1, %%mm0         \n\t"
 +
 +        "movq %%mm0, (%%"REG_D")           \n\t"
 +        "add $16, %%"REG_S"              \n\t"
 +        "add $8, %%"REG_D"               \n\t"
 +        "sub $8, %%"REG_c"               \n\t"
 +        "jg 1b                      \n\t"
 +        "add %1, %%"REG_S"       \n\t"
 +        "add $8, %%"REG_d"               \n\t"
 +        "add %3, %%"REG_D"       \n\t"
 +        "cmp %4, %%"REG_d"           \n\t"
 +        "jl 2b                      \n\t"
 +
 +        :
 +        : "m" (width), "m" (src_stride), "erm" (od), "m" (dst_stride), "erm" (end),
 +          "m" (log2_scale), "m" (src), "m" (dst) //input
 +        : "%"REG_a, "%"REG_c, "%"REG_d, "%"REG_D, "%"REG_S
 +        );
 +}
 +
 +static void mul_thrmat_mmx(struct vf_priv_s *p, int q)
 +{
 +    uint64_t *adr=&p->threshold_mtx_noq[0];
 +    __asm__ volatile(
 +        "movd %0, %%mm7                \n\t"
 +        "add $8*8*2, %%"REG_D"            \n\t"
 +        "movq 0*8(%%"REG_S"), %%mm0        \n\t"
 +        "punpcklwd %%mm7, %%mm7        \n\t"
 +        "movq 1*8(%%"REG_S"), %%mm1        \n\t"
 +        "punpckldq %%mm7, %%mm7        \n\t"
 +        "pmullw %%mm7, %%mm0           \n\t"
 +
 +        "movq 2*8(%%"REG_S"), %%mm2        \n\t"
 +        "pmullw %%mm7, %%mm1           \n\t"
 +
 +        "movq 3*8(%%"REG_S"), %%mm3        \n\t"
 +        "pmullw %%mm7, %%mm2           \n\t"
 +
 +        "movq %%mm0, 0*8(%%"REG_D")        \n\t"
 +        "movq 4*8(%%"REG_S"), %%mm4        \n\t"
 +        "pmullw %%mm7, %%mm3           \n\t"
 +
 +        "movq %%mm1, 1*8(%%"REG_D")        \n\t"
 +        "movq 5*8(%%"REG_S"), %%mm5        \n\t"
 +        "pmullw %%mm7, %%mm4           \n\t"
 +
 +        "movq %%mm2, 2*8(%%"REG_D")        \n\t"
 +        "movq 6*8(%%"REG_S"), %%mm6        \n\t"
 +        "pmullw %%mm7, %%mm5           \n\t"
 +
 +        "movq %%mm3, 3*8(%%"REG_D")        \n\t"
 +        "movq 7*8+0*8(%%"REG_S"), %%mm0    \n\t"
 +        "pmullw %%mm7, %%mm6           \n\t"
 +
 +        "movq %%mm4, 4*8(%%"REG_D")        \n\t"
 +        "movq 7*8+1*8(%%"REG_S"), %%mm1    \n\t"
 +        "pmullw %%mm7, %%mm0           \n\t"
 +
 +        "movq %%mm5, 5*8(%%"REG_D")        \n\t"
 +        "movq 7*8+2*8(%%"REG_S"), %%mm2    \n\t"
 +        "pmullw %%mm7, %%mm1           \n\t"
 +
 +        "movq %%mm6, 6*8(%%"REG_D")        \n\t"
 +        "movq 7*8+3*8(%%"REG_S"), %%mm3    \n\t"
 +        "pmullw %%mm7, %%mm2           \n\t"
 +
 +        "movq %%mm0, 7*8+0*8(%%"REG_D")    \n\t"
 +        "movq 7*8+4*8(%%"REG_S"), %%mm4    \n\t"
 +        "pmullw %%mm7, %%mm3           \n\t"
 +
 +        "movq %%mm1, 7*8+1*8(%%"REG_D")    \n\t"
 +        "movq 7*8+5*8(%%"REG_S"), %%mm5    \n\t"
 +        "pmullw %%mm7, %%mm4           \n\t"
 +
 +        "movq %%mm2, 7*8+2*8(%%"REG_D")    \n\t"
 +        "movq 7*8+6*8(%%"REG_S"), %%mm6    \n\t"
 +        "pmullw %%mm7, %%mm5           \n\t"
 +
 +        "movq %%mm3, 7*8+3*8(%%"REG_D")    \n\t"
 +        "movq 14*8+0*8(%%"REG_S"), %%mm0   \n\t"
 +        "pmullw %%mm7, %%mm6           \n\t"
 +
 +        "movq %%mm4, 7*8+4*8(%%"REG_D")    \n\t"
 +        "movq 14*8+1*8(%%"REG_S"), %%mm1   \n\t"
 +        "pmullw %%mm7, %%mm0           \n\t"
 +
 +        "movq %%mm5, 7*8+5*8(%%"REG_D")    \n\t"
 +        "pmullw %%mm7, %%mm1           \n\t"
 +
 +        "movq %%mm6, 7*8+6*8(%%"REG_D")    \n\t"
 +        "movq %%mm0, 14*8+0*8(%%"REG_D")   \n\t"
 +        "movq %%mm1, 14*8+1*8(%%"REG_D")   \n\t"
 +
 +        : "+g" (q), "+S" (adr), "+D" (adr)
 +        :
 +        );
 +}
 +
- static void row_fdct_mmx(DCTELEM *data,  const uint8_t *pixels,  int line_size,  int cnt);
++static void column_fidct_mmx(int16_t* thr_adr,  int16_t *data,  int16_t *output,  int cnt);
++static void row_idct_mmx(int16_t* workspace,
 +                         int16_t* output_adr,  int output_stride,  int cnt);
-     DCTELEM *block= (DCTELEM *)block_align;
-     DCTELEM *block3=(DCTELEM *)(block_align+4*8*BLOCKSZ);
++static void row_fdct_mmx(int16_t *data,  const uint8_t *pixels,  int line_size,  int cnt);
 +
 +#define store_slice_s store_slice_mmx
 +#define store_slice2_s store_slice2_mmx
 +#define mul_thrmat_s mul_thrmat_mmx
 +#define column_fidct_s column_fidct_mmx
 +#define row_idct_s row_idct_mmx
 +#define row_fdct_s row_fdct_mmx
 +#endif // HAVE_MMX
 +
 +static void filter(struct vf_priv_s *p, uint8_t *dst, uint8_t *src,
 +                   int dst_stride, int src_stride,
 +                   int width, int height,
 +                   uint8_t *qp_store, int qp_stride, int is_luma)
 +{
 +    int x, x0, y, es, qy, t;
 +    const int stride= is_luma ? p->temp_stride : (width+16);//((width+16+15)&(~15))
 +    const int step=6-p->log2_count;
 +    const int qps= 3 + is_luma;
 +    int32_t __attribute__((aligned(32))) block_align[4*8*BLOCKSZ+ 4*8*BLOCKSZ];
-             memmove(block, block+(BLOCKSZ-1)*64, 8*8*sizeof(DCTELEM)); //cycling
-             memmove(block3, block3+(BLOCKSZ-1)*64, 6*8*sizeof(DCTELEM));
++    int16_t *block= (int16_t *)block_align;
++    int16_t *block3=(int16_t *)(block_align+4*8*BLOCKSZ);
 +
 +    memset(block3, 0, 4*8*BLOCKSZ);
 +
 +    //p->src=src-src_stride*8-8;//!
 +    if (!src || !dst) return; // HACK avoid crash for Y8 colourspace
 +    for(y=0; y<height; y++){
 +        int index= 8 + 8*stride + y*stride;
 +        fast_memcpy(p->src + index, src + y*src_stride, width);//this line can be avoided by using DR & user fr.buffers
 +        for(x=0; x<8; x++){
 +            p->src[index         - x - 1]= p->src[index +         x    ];
 +            p->src[index + width + x    ]= p->src[index + width - x - 1];
 +        }
 +    }
 +    for(y=0; y<8; y++){
 +        fast_memcpy(p->src + (      7-y)*stride, p->src + (      y+8)*stride, stride);
 +        fast_memcpy(p->src + (height+8+y)*stride, p->src + (height-y+7)*stride, stride);
 +    }
 +    //FIXME (try edge emu)
 +
 +    for(y=8; y<24; y++)
 +        memset(p->temp+ 8 +y*stride, 0,width*sizeof(int16_t));
 +
 +    for(y=step; y<height+8; y+=step){    //step= 1,2
 +        qy=y-4;
 +        if (qy>height-1) qy=height-1;
 +        if (qy<0) qy=0;
 +        qy=(qy>>qps)*qp_stride;
 +        row_fdct_s(block, p->src + y*stride +2-(y&1), stride, 2);
 +        for(x0=0; x0<width+8-8*(BLOCKSZ-1); x0+=8*(BLOCKSZ-1)){
 +            row_fdct_s(block+8*8, p->src + y*stride+8+x0 +2-(y&1), stride, 2*(BLOCKSZ-1));
 +            if(p->qp)
 +                column_fidct_s((int16_t*)(&p->threshold_mtx[0]), block+0*8, block3+0*8, 8*(BLOCKSZ-1)); //yes, this is a HOTSPOT
 +            else
 +                for (x=0; x<8*(BLOCKSZ-1); x+=8) {
 +                    t=x+x0-2; //correct t=x+x0-2-(y&1), but its the same
 +                    if (t<0) t=0;//t always < width-2
 +                    t=qp_store[qy+(t>>qps)];
 +                    t=norm_qscale(t, p->mpeg2);
 +                    if (t!=p->prev_q) p->prev_q=t, mul_thrmat_s(p, t);
 +                    column_fidct_s((int16_t*)(&p->threshold_mtx[0]), block+x*8, block3+x*8, 8); //yes, this is a HOTSPOT
 +                }
 +            row_idct_s(block3+0*8, p->temp + (y&15)*stride+x0+2-(y&1), stride, 2*(BLOCKSZ-1));
- //typedef int16_t DCTELEM; //! only int16_t
++            memmove(block, block+(BLOCKSZ-1)*64, 8*8*sizeof(int16_t)); //cycling
++            memmove(block3, block3+(BLOCKSZ-1)*64, 6*8*sizeof(int16_t));
 +        }
 +        //
 +        es=width+8-x0; //  8, ...
 +        if (es>8)
 +            row_fdct_s(block+8*8, p->src + y*stride+8+x0 +2-(y&1), stride, (es-4)>>2);
 +        column_fidct_s((int16_t*)(&p->threshold_mtx[0]), block, block3, es&(~1));
 +        row_idct_s(block3+0*8, p->temp + (y&15)*stride+x0+2-(y&1), stride, es>>2);
 +        {const int y1=y-8+step;//l5-7  l4-6
 +            if (!(y1&7) && y1) {
 +                if (y1&8) store_slice_s(dst + (y1-8)*dst_stride, p->temp+ 8 +8*stride,
 +                                        dst_stride, stride, width, 8, 5-p->log2_count);
 +                else store_slice2_s(dst + (y1-8)*dst_stride, p->temp+ 8 +0*stride,
 +                                    dst_stride, stride, width, 8, 5-p->log2_count);
 +            } }
 +    }
 +
 +    if (y&7) {  // == height & 7
 +        if (y&8) store_slice_s(dst + ((y-8)&~7)*dst_stride, p->temp+ 8 +8*stride,
 +                               dst_stride, stride, width, y&7, 5-p->log2_count);
 +        else store_slice2_s(dst + ((y-8)&~7)*dst_stride, p->temp+ 8 +0*stride,
 +                            dst_stride, stride, width, y&7, 5-p->log2_count);
 +    }
 +}
 +
 +static int config(struct vf_instance *vf,
 +                  int width, int height, int d_width, int d_height,
 +                  unsigned int flags, unsigned int outfmt)
 +{
 +    int h= (height+16+15)&(~15);
 +
 +    vf->priv->temp_stride= (width+16+15)&(~15);
 +    vf->priv->temp= (int16_t*)av_mallocz(vf->priv->temp_stride*3*8*sizeof(int16_t));
 +    //this can also be avoided, see above
 +    vf->priv->src = (uint8_t*)av_malloc(vf->priv->temp_stride*h*sizeof(uint8_t));
 +
 +    return ff_vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
 +}
 +
 +static void get_image(struct vf_instance *vf, mp_image_t *mpi)
 +{
 +    if(mpi->flags&MP_IMGFLAG_PRESERVE) return; // don't change
 +    // ok, we can do pp in-place (or pp disabled):
 +    vf->dmpi=ff_vf_get_image(vf->next,mpi->imgfmt,
 +                          mpi->type, mpi->flags, mpi->width, mpi->height);
 +    mpi->planes[0]=vf->dmpi->planes[0];
 +    mpi->stride[0]=vf->dmpi->stride[0];
 +    mpi->width=vf->dmpi->width;
 +    if(mpi->flags&MP_IMGFLAG_PLANAR){
 +        mpi->planes[1]=vf->dmpi->planes[1];
 +        mpi->planes[2]=vf->dmpi->planes[2];
 +        mpi->stride[1]=vf->dmpi->stride[1];
 +        mpi->stride[2]=vf->dmpi->stride[2];
 +    }
 +    mpi->flags|=MP_IMGFLAG_DIRECT;
 +}
 +
 +static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
 +{
 +    mp_image_t *dmpi;
 +    if(!(mpi->flags&MP_IMGFLAG_DIRECT)){
 +        // no DR, so get a new image! hope we'll get DR buffer:
 +        dmpi=ff_vf_get_image(vf->next,mpi->imgfmt,
 +                          MP_IMGTYPE_TEMP,
 +                          MP_IMGFLAG_ACCEPT_STRIDE|MP_IMGFLAG_PREFER_ALIGNED_STRIDE,
 +                          mpi->width,mpi->height);
 +        ff_vf_clone_mpi_attributes(dmpi, mpi);
 +    }else{
 +        dmpi=vf->dmpi;
 +    }
 +
 +    vf->priv->mpeg2= mpi->qscale_type;
 +    if(mpi->pict_type != 3 && mpi->qscale && !vf->priv->qp){
 +        int w = mpi->qstride;
 +        int h = (mpi->h + 15) >> 4;
 +        if (!w) {
 +            w = (mpi->w + 15) >> 4;
 +            h = 1;
 +        }
 +        if(!vf->priv->non_b_qp)
 +            vf->priv->non_b_qp= malloc(w*h);
 +        fast_memcpy(vf->priv->non_b_qp, mpi->qscale, w*h);
 +    }
 +    if(vf->priv->log2_count || !(mpi->flags&MP_IMGFLAG_DIRECT)){
 +        char *qp_tab= vf->priv->non_b_qp;
 +        if(vf->priv->bframes || !qp_tab)
 +            qp_tab= mpi->qscale;
 +
 +        if(qp_tab || vf->priv->qp){
 +            filter(vf->priv, dmpi->planes[0], mpi->planes[0], dmpi->stride[0], mpi->stride[0],
 +                   mpi->w, mpi->h, qp_tab, mpi->qstride, 1);
 +            filter(vf->priv, dmpi->planes[1], mpi->planes[1], dmpi->stride[1], mpi->stride[1],
 +                   mpi->w>>mpi->chroma_x_shift, mpi->h>>mpi->chroma_y_shift, qp_tab, mpi->qstride, 0);
 +            filter(vf->priv, dmpi->planes[2], mpi->planes[2], dmpi->stride[2], mpi->stride[2],
 +                   mpi->w>>mpi->chroma_x_shift, mpi->h>>mpi->chroma_y_shift, qp_tab, mpi->qstride, 0);
 +        }else{
 +            memcpy_pic(dmpi->planes[0], mpi->planes[0], mpi->w, mpi->h, dmpi->stride[0], mpi->stride[0]);
 +            memcpy_pic(dmpi->planes[1], mpi->planes[1], mpi->w>>mpi->chroma_x_shift, mpi->h>>mpi->chroma_y_shift, dmpi->stride[1], mpi->stride[1]);
 +            memcpy_pic(dmpi->planes[2], mpi->planes[2], mpi->w>>mpi->chroma_x_shift, mpi->h>>mpi->chroma_y_shift, dmpi->stride[2], mpi->stride[2]);
 +        }
 +    }
 +
 +#if HAVE_MMX
 +    if(ff_gCpuCaps.hasMMX) __asm__ volatile ("emms\n\t");
 +#endif
 +#if HAVE_MMX2
 +    if(ff_gCpuCaps.hasMMX2) __asm__ volatile ("sfence\n\t");
 +#endif
 +    return ff_vf_next_put_image(vf,dmpi, pts);
 +}
 +
 +static void uninit(struct vf_instance *vf)
 +{
 +    if(!vf->priv) return;
 +
 +    av_free(vf->priv->temp);
 +    vf->priv->temp= NULL;
 +    av_free(vf->priv->src);
 +    vf->priv->src= NULL;
 +    //free(vf->priv->avctx);
 +    //vf->priv->avctx= NULL;
 +    free(vf->priv->non_b_qp);
 +    vf->priv->non_b_qp= NULL;
 +
 +    av_free(vf->priv);
 +    vf->priv=NULL;
 +}
 +
 +//===========================================================================//
 +
 +static int query_format(struct vf_instance *vf, unsigned int fmt)
 +{
 +    switch(fmt){
 +    case IMGFMT_YVU9:
 +    case IMGFMT_IF09:
 +    case IMGFMT_YV12:
 +    case IMGFMT_I420:
 +    case IMGFMT_IYUV:
 +    case IMGFMT_CLPL:
 +    case IMGFMT_Y800:
 +    case IMGFMT_Y8:
 +    case IMGFMT_444P:
 +    case IMGFMT_422P:
 +    case IMGFMT_411P:
 +        return ff_vf_next_query_format(vf,fmt);
 +    }
 +    return 0;
 +}
 +
 +static int control(struct vf_instance *vf, int request, void* data)
 +{
 +    switch(request){
 +    case VFCTRL_QUERY_MAX_PP_LEVEL:
 +        return 5;
 +    case VFCTRL_SET_PP_LEVEL:
 +        vf->priv->log2_count= *((unsigned int*)data);
 +        if (vf->priv->log2_count < 4) vf->priv->log2_count=4;
 +        return CONTROL_TRUE;
 +    }
 +    return ff_vf_next_control(vf,request,data);
 +}
 +
 +static int vf_open(vf_instance_t *vf, char *args)
 +{
 +    int i=0, bias;
 +    int custom_threshold_m[64];
 +    int log2c=-1;
 +
 +    vf->config=config;
 +    vf->put_image=put_image;
 +    vf->get_image=get_image;
 +    vf->query_format=query_format;
 +    vf->uninit=uninit;
 +    vf->control= control;
 +    vf->priv=av_mallocz(sizeof(struct vf_priv_s));//assumes align 16 !
 +
 +    ff_init_avcodec();
 +
 +    //vf->priv->avctx= avcodec_alloc_context();
 +    //dsputil_init(&vf->priv->dsp, vf->priv->avctx);
 +
 +    vf->priv->log2_count= 4;
 +    vf->priv->bframes = 0;
 +
 +    if (args) sscanf(args, "%d:%d:%d:%d", &log2c, &vf->priv->qp, &i, &vf->priv->bframes);
 +
 +    if( log2c >=4 && log2c <=5 )
 +        vf->priv->log2_count = log2c;
 +    else if( log2c >= 6 )
 +        vf->priv->log2_count = 5;
 +
 +    if(vf->priv->qp < 0)
 +        vf->priv->qp = 0;
 +
 +    if (i < -15) i = -15;
 +    if (i > 32) i = 32;
 +
 +    bias= (1<<4)+i; //regulable
 +    vf->priv->prev_q=0;
 +    //
 +    for(i=0;i<64;i++) //FIXME: tune custom_threshold[] and remove this !
 +        custom_threshold_m[i]=(int)(custom_threshold[i]*(bias/71.)+ 0.5);
 +    for(i=0;i<8;i++){
 +        vf->priv->threshold_mtx_noq[2*i]=(uint64_t)custom_threshold_m[i*8+2]
 +            |(((uint64_t)custom_threshold_m[i*8+6])<<16)
 +            |(((uint64_t)custom_threshold_m[i*8+0])<<32)
 +            |(((uint64_t)custom_threshold_m[i*8+4])<<48);
 +        vf->priv->threshold_mtx_noq[2*i+1]=(uint64_t)custom_threshold_m[i*8+5]
 +            |(((uint64_t)custom_threshold_m[i*8+3])<<16)
 +            |(((uint64_t)custom_threshold_m[i*8+1])<<32)
 +            |(((uint64_t)custom_threshold_m[i*8+7])<<48);
 +    }
 +
 +    if (vf->priv->qp) vf->priv->prev_q=vf->priv->qp, mul_thrmat_s(vf->priv, vf->priv->qp);
 +
 +    return 1;
 +}
 +
 +const vf_info_t ff_vf_info_fspp = {
 +    "fast simple postprocess",
 +    "fspp",
 +    "Michael Niedermayer, Nikolaj Poroshin",
 +    "",
 +    vf_open,
 +    NULL
 +};
 +
 +//====================================================================
 +//Specific spp's dct, idct and threshold functions
 +//I'd prefer to have them in the separate file.
 +
 +//#define MANGLE(a) #a
 +
- static void column_fidct_c(int16_t* thr_adr, DCTELEM *data, DCTELEM *output, int cnt)
++//typedef int16_t int16_t; //! only int16_t
 +
 +#define DCTSIZE 8
 +#define DCTSIZE_S "8"
 +
 +#define FIX(x,s)  ((int) ((x) * (1<<s) + 0.5)&0xffff)
 +#define C64(x)    ((uint64_t)((x)|(x)<<16))<<32 | (uint64_t)(x) | (uint64_t)(x)<<16
 +#define FIX64(x,s)  C64(FIX(x,s))
 +
 +#define MULTIPLY16H(x,k)   (((x)*(k))>>16)
 +#define THRESHOLD(r,x,t) if(((unsigned)((x)+t))>t*2) r=(x);else r=0;
 +#define DESCALE(x,n)  (((x) + (1 << ((n)-1))) >> n)
 +
 +#if HAVE_MMX
 +
 +DECLARE_ASM_CONST(8, uint64_t, MM_FIX_0_382683433)=FIX64(0.382683433, 14);
 +DECLARE_ALIGNED(8, uint64_t, ff_MM_FIX_0_541196100)=FIX64(0.541196100, 14);
 +DECLARE_ALIGNED(8, uint64_t, ff_MM_FIX_0_707106781)=FIX64(0.707106781, 14);
 +DECLARE_ASM_CONST(8, uint64_t, MM_FIX_1_306562965)=FIX64(1.306562965, 14);
 +
 +DECLARE_ASM_CONST(8, uint64_t, MM_FIX_1_414213562_A)=FIX64(1.414213562, 14);
 +
 +DECLARE_ASM_CONST(8, uint64_t, MM_FIX_1_847759065)=FIX64(1.847759065, 13);
 +DECLARE_ASM_CONST(8, uint64_t, MM_FIX_2_613125930)=FIX64(-2.613125930, 13); //-
 +DECLARE_ASM_CONST(8, uint64_t, MM_FIX_1_414213562)=FIX64(1.414213562, 13);
 +DECLARE_ASM_CONST(8, uint64_t, MM_FIX_1_082392200)=FIX64(1.082392200, 13);
 +//for t3,t5,t7 == 0 shortcut
 +DECLARE_ASM_CONST(8, uint64_t, MM_FIX_0_847759065)=FIX64(0.847759065, 14);
 +DECLARE_ASM_CONST(8, uint64_t, MM_FIX_0_566454497)=FIX64(0.566454497, 14);
 +DECLARE_ASM_CONST(8, uint64_t, MM_FIX_0_198912367)=FIX64(0.198912367, 14);
 +
 +DECLARE_ASM_CONST(8, uint64_t, MM_DESCALE_RND)=C64(4);
 +DECLARE_ASM_CONST(8, uint64_t, MM_2)=C64(2);
 +
 +#else /* !HAVE_MMX */
 +
 +typedef int32_t int_simd16_t;
 +static const int16_t FIX_0_382683433=FIX(0.382683433, 14);
 +static const int16_t FIX_0_541196100=FIX(0.541196100, 14);
 +static const int16_t FIX_0_707106781=FIX(0.707106781, 14);
 +static const int16_t FIX_1_306562965=FIX(1.306562965, 14);
 +static const int16_t FIX_1_414213562_A=FIX(1.414213562, 14);
 +static const int16_t FIX_1_847759065=FIX(1.847759065, 13);
 +static const int16_t FIX_2_613125930=FIX(-2.613125930, 13); //-
 +static const int16_t FIX_1_414213562=FIX(1.414213562, 13);
 +static const int16_t FIX_1_082392200=FIX(1.082392200, 13);
 +
 +#endif
 +
 +#if !HAVE_MMX
 +
-     DCTELEM* dataptr;
-     DCTELEM* wsptr;
++static void column_fidct_c(int16_t* thr_adr, int16_t *data, int16_t *output, int cnt)
 +{
 +    int_simd16_t tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
 +    int_simd16_t tmp10, tmp11, tmp12, tmp13;
 +    int_simd16_t z1,z2,z3,z4,z5, z10, z11, z12, z13;
 +    int_simd16_t d0, d1, d2, d3, d4, d5, d6, d7;
 +
- static void column_fidct_mmx(int16_t* thr_adr,  DCTELEM *data,  DCTELEM *output,  int cnt)
++    int16_t* dataptr;
++    int16_t* wsptr;
 +    int16_t *threshold;
 +    int ctr;
 +
 +    dataptr = data;
 +    wsptr = output;
 +
 +    for (; cnt > 0; cnt-=2) { //start positions
 +        threshold=(int16_t*)thr_adr;//threshold_mtx
 +        for (ctr = DCTSIZE; ctr > 0; ctr--) {
 +            // Process columns from input, add to output.
 +            tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7];
 +            tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7];
 +
 +            tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6];
 +            tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6];
 +
 +            tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5];
 +            tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5];
 +
 +            tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4];
 +            tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4];
 +
 +            // Even part of FDCT
 +
 +            tmp10 = tmp0 + tmp3;
 +            tmp13 = tmp0 - tmp3;
 +            tmp11 = tmp1 + tmp2;
 +            tmp12 = tmp1 - tmp2;
 +
 +            d0 = tmp10 + tmp11;
 +            d4 = tmp10 - tmp11;
 +
 +            z1 = MULTIPLY16H((tmp12 + tmp13) <<2, FIX_0_707106781);
 +            d2 = tmp13 + z1;
 +            d6 = tmp13 - z1;
 +
 +            // Even part of IDCT
 +
 +            THRESHOLD(tmp0, d0, threshold[0*8]);
 +            THRESHOLD(tmp1, d2, threshold[2*8]);
 +            THRESHOLD(tmp2, d4, threshold[4*8]);
 +            THRESHOLD(tmp3, d6, threshold[6*8]);
 +            tmp0+=2;
 +            tmp10 = (tmp0 + tmp2)>>2;
 +            tmp11 = (tmp0 - tmp2)>>2;
 +
 +            tmp13 = (tmp1 + tmp3)>>2; //+2 !  (psnr decides)
 +            tmp12 = MULTIPLY16H((tmp1 - tmp3), FIX_1_414213562_A) - tmp13; //<<2
 +
 +            tmp0 = tmp10 + tmp13; //->temps
 +            tmp3 = tmp10 - tmp13; //->temps
 +            tmp1 = tmp11 + tmp12; //->temps
 +            tmp2 = tmp11 - tmp12; //->temps
 +
 +            // Odd part of FDCT
 +
 +            tmp10 = tmp4 + tmp5;
 +            tmp11 = tmp5 + tmp6;
 +            tmp12 = tmp6 + tmp7;
 +
 +            z5 = MULTIPLY16H((tmp10 - tmp12)<<2, FIX_0_382683433);
 +            z2 = MULTIPLY16H(tmp10 <<2, FIX_0_541196100) + z5;
 +            z4 = MULTIPLY16H(tmp12 <<2, FIX_1_306562965) + z5;
 +            z3 = MULTIPLY16H(tmp11 <<2, FIX_0_707106781);
 +
 +            z11 = tmp7 + z3;
 +            z13 = tmp7 - z3;
 +
 +            d5 = z13 + z2;
 +            d3 = z13 - z2;
 +            d1 = z11 + z4;
 +            d7 = z11 - z4;
 +
 +            // Odd part of IDCT
 +
 +            THRESHOLD(tmp4, d1, threshold[1*8]);
 +            THRESHOLD(tmp5, d3, threshold[3*8]);
 +            THRESHOLD(tmp6, d5, threshold[5*8]);
 +            THRESHOLD(tmp7, d7, threshold[7*8]);
 +
 +            //Simd version uses here a shortcut for the tmp5,tmp6,tmp7 == 0
 +            z13 = tmp6 + tmp5;
 +            z10 = (tmp6 - tmp5)<<1;
 +            z11 = tmp4 + tmp7;
 +            z12 = (tmp4 - tmp7)<<1;
 +
 +            tmp7 = (z11 + z13)>>2; //+2 !
 +            tmp11 = MULTIPLY16H((z11 - z13)<<1, FIX_1_414213562);
 +            z5 =    MULTIPLY16H(z10 + z12, FIX_1_847759065);
 +            tmp10 = MULTIPLY16H(z12, FIX_1_082392200) - z5;
 +            tmp12 = MULTIPLY16H(z10, FIX_2_613125930) + z5; // - !!
 +
 +            tmp6 = tmp12 - tmp7;
 +            tmp5 = tmp11 - tmp6;
 +            tmp4 = tmp10 + tmp5;
 +
 +            wsptr[DCTSIZE*0]+=  (tmp0 + tmp7);
 +            wsptr[DCTSIZE*1]+=  (tmp1 + tmp6);
 +            wsptr[DCTSIZE*2]+=  (tmp2 + tmp5);
 +            wsptr[DCTSIZE*3]+=  (tmp3 - tmp4);
 +            wsptr[DCTSIZE*4]+=  (tmp3 + tmp4);
 +            wsptr[DCTSIZE*5]+=  (tmp2 - tmp5);
 +            wsptr[DCTSIZE*6]=  (tmp1 - tmp6);
 +            wsptr[DCTSIZE*7]=  (tmp0 - tmp7);
 +            //
 +            dataptr++; //next column
 +            wsptr++;
 +            threshold++;
 +        }
 +        dataptr+=8; //skip each second start pos
 +        wsptr  +=8;
 +    }
 +}
 +
 +#else /* HAVE_MMX */
 +
- static void row_idct_c(DCTELEM* workspace,
++static void column_fidct_mmx(int16_t* thr_adr,  int16_t *data,  int16_t *output,  int cnt)
 +{
 +    uint64_t __attribute__((aligned(8))) temps[4];
 +    __asm__ volatile(
 +        ASMALIGN(4)
 +        "1:                   \n\t"
 +        "movq "DCTSIZE_S"*0*2(%%"REG_S"), %%mm1 \n\t"
 +        //
 +        "movq "DCTSIZE_S"*3*2(%%"REG_S"), %%mm7 \n\t"
 +        "movq %%mm1, %%mm0             \n\t"
 +
 +        "paddw "DCTSIZE_S"*7*2(%%"REG_S"), %%mm1 \n\t" //t0
 +        "movq %%mm7, %%mm3             \n\t"
 +
 +        "paddw "DCTSIZE_S"*4*2(%%"REG_S"), %%mm7 \n\t" //t3
 +        "movq %%mm1, %%mm5             \n\t"
 +
 +        "movq "DCTSIZE_S"*1*2(%%"REG_S"), %%mm6 \n\t"
 +        "psubw %%mm7, %%mm1            \n\t" //t13
 +
 +        "movq "DCTSIZE_S"*2*2(%%"REG_S"), %%mm2 \n\t"
 +        "movq %%mm6, %%mm4             \n\t"
 +
 +        "paddw "DCTSIZE_S"*6*2(%%"REG_S"), %%mm6 \n\t" //t1
 +        "paddw %%mm7, %%mm5            \n\t" //t10
 +
 +        "paddw "DCTSIZE_S"*5*2(%%"REG_S"), %%mm2 \n\t" //t2
 +        "movq %%mm6, %%mm7             \n\t"
 +
 +        "paddw %%mm2, %%mm6            \n\t" //t11
 +        "psubw %%mm2, %%mm7            \n\t" //t12
 +
 +        "movq %%mm5, %%mm2             \n\t"
 +        "paddw %%mm6, %%mm5            \n\t" //d0
 +        // i0 t13 t12 i3 i1 d0 - d4
 +        "psubw %%mm6, %%mm2            \n\t" //d4
 +        "paddw %%mm1, %%mm7            \n\t"
 +
 +        "movq  4*16(%%"REG_d"), %%mm6      \n\t"
 +        "psllw $2, %%mm7              \n\t"
 +
 +        "psubw 0*16(%%"REG_d"), %%mm5      \n\t"
 +        "psubw %%mm6, %%mm2            \n\t"
 +
 +        "paddusw 0*16(%%"REG_d"), %%mm5    \n\t"
 +        "paddusw %%mm6, %%mm2          \n\t"
 +
 +        "pmulhw "MANGLE(ff_MM_FIX_0_707106781)", %%mm7 \n\t"
 +        //
 +        "paddw 0*16(%%"REG_d"), %%mm5      \n\t"
 +        "paddw %%mm6, %%mm2            \n\t"
 +
 +        "psubusw 0*16(%%"REG_d"), %%mm5    \n\t"
 +        "psubusw %%mm6, %%mm2          \n\t"
 +
 +//This func is totally compute-bound,  operates at huge speed. So,  DC shortcut
 +// at this place isn't worthwhile due to BTB miss penalty (checked on Pent. 3).
 +//However,  typical numbers: nondc - 29%%,  dc - 46%%,  zero - 25%%. All <> 0 case is very rare.
 +        "paddw "MANGLE(MM_2)", %%mm5            \n\t"
 +        "movq %%mm2, %%mm6             \n\t"
 +
 +        "paddw %%mm5, %%mm2            \n\t"
 +        "psubw %%mm6, %%mm5            \n\t"
 +
 +        "movq %%mm1, %%mm6             \n\t"
 +        "paddw %%mm7, %%mm1            \n\t" //d2
 +
 +        "psubw 2*16(%%"REG_d"), %%mm1      \n\t"
 +        "psubw %%mm7, %%mm6            \n\t" //d6
 +
 +        "movq 6*16(%%"REG_d"), %%mm7       \n\t"
 +        "psraw $2, %%mm5              \n\t"
 +
 +        "paddusw 2*16(%%"REG_d"), %%mm1    \n\t"
 +        "psubw %%mm7, %%mm6            \n\t"
 +        // t7 d2 /t11 t4 t6 - d6 /t10
 +
 +        "paddw 2*16(%%"REG_d"), %%mm1      \n\t"
 +        "paddusw %%mm7, %%mm6          \n\t"
 +
 +        "psubusw 2*16(%%"REG_d"), %%mm1    \n\t"
 +        "paddw %%mm7, %%mm6            \n\t"
 +
 +        "psubw "DCTSIZE_S"*4*2(%%"REG_S"), %%mm3 \n\t"
 +        "psubusw %%mm7, %%mm6          \n\t"
 +
 +        //movq [edi+"DCTSIZE_S"*2*2], mm1
 +        //movq [edi+"DCTSIZE_S"*6*2], mm6
 +        "movq %%mm1, %%mm7             \n\t"
 +        "psraw $2, %%mm2              \n\t"
 +
 +        "psubw "DCTSIZE_S"*6*2(%%"REG_S"), %%mm4 \n\t"
 +        "psubw %%mm6, %%mm1            \n\t"
 +
 +        "psubw "DCTSIZE_S"*7*2(%%"REG_S"), %%mm0 \n\t"
 +        "paddw %%mm7, %%mm6            \n\t" //'t13
 +
 +        "psraw $2, %%mm6              \n\t" //paddw mm6, MM_2 !!    ---
 +        "movq %%mm2, %%mm7             \n\t"
 +
 +        "pmulhw "MANGLE(MM_FIX_1_414213562_A)", %%mm1 \n\t"
 +        "paddw %%mm6, %%mm2            \n\t" //'t0
 +
 +        "movq %%mm2, 0*8+%3            \n\t" //!
 +        "psubw %%mm6, %%mm7            \n\t" //'t3
 +
 +        "movq "DCTSIZE_S"*2*2(%%"REG_S"), %%mm2 \n\t"
 +        "psubw %%mm6, %%mm1            \n\t" //'t12
 +
 +        "psubw "DCTSIZE_S"*5*2(%%"REG_S"), %%mm2 \n\t" //t5
 +        "movq %%mm5, %%mm6             \n\t"
 +
 +        "movq %%mm7, 3*8+%3            \n\t"
 +        "paddw %%mm2, %%mm3            \n\t" //t10
 +
 +        "paddw %%mm4, %%mm2            \n\t" //t11
 +        "paddw %%mm0, %%mm4            \n\t" //t12
 +
 +        "movq %%mm3, %%mm7             \n\t"
 +        "psubw %%mm4, %%mm3            \n\t"
 +
 +        "psllw $2, %%mm3              \n\t"
 +        "psllw $2, %%mm7              \n\t" //opt for P6
 +
 +        "pmulhw "MANGLE(MM_FIX_0_382683433)", %%mm3 \n\t"
 +        "psllw $2, %%mm4              \n\t"
 +
 +        "pmulhw "MANGLE(ff_MM_FIX_0_541196100)", %%mm7 \n\t"
 +        "psllw $2, %%mm2              \n\t"
 +
 +        "pmulhw "MANGLE(MM_FIX_1_306562965)", %%mm4 \n\t"
 +        "paddw %%mm1, %%mm5            \n\t" //'t1
 +
 +        "pmulhw "MANGLE(ff_MM_FIX_0_707106781)", %%mm2 \n\t"
 +        "psubw %%mm1, %%mm6            \n\t" //'t2
 +        // t7 't12 't11 t4 t6 - 't13 't10   ---
 +
 +        "paddw %%mm3, %%mm7            \n\t" //z2
 +
 +        "movq %%mm5, 1*8+%3            \n\t"
 +        "paddw %%mm3, %%mm4            \n\t" //z4
 +
 +        "movq 3*16(%%"REG_d"), %%mm3       \n\t"
 +        "movq %%mm0, %%mm1             \n\t"
 +
 +        "movq %%mm6, 2*8+%3            \n\t"
 +        "psubw %%mm2, %%mm1            \n\t" //z13
 +
 +//===
 +        "paddw %%mm2, %%mm0            \n\t" //z11
 +        "movq %%mm1, %%mm5             \n\t"
 +
 +        "movq 5*16(%%"REG_d"), %%mm2       \n\t"
 +        "psubw %%mm7, %%mm1            \n\t" //d3
 +
 +        "paddw %%mm7, %%mm5            \n\t" //d5
 +        "psubw %%mm3, %%mm1            \n\t"
 +
 +        "movq 1*16(%%"REG_d"), %%mm7       \n\t"
 +        "psubw %%mm2, %%mm5            \n\t"
 +
 +        "movq %%mm0, %%mm6             \n\t"
 +        "paddw %%mm4, %%mm0            \n\t" //d1
 +
 +        "paddusw %%mm3, %%mm1          \n\t"
 +        "psubw %%mm4, %%mm6            \n\t" //d7
 +
 +        // d1 d3 - - - d5 d7 -
 +        "movq 7*16(%%"REG_d"), %%mm4       \n\t"
 +        "psubw %%mm7, %%mm0            \n\t"
 +
 +        "psubw %%mm4, %%mm6            \n\t"
 +        "paddusw %%mm2, %%mm5          \n\t"
 +
 +        "paddusw %%mm4, %%mm6          \n\t"
 +        "paddw %%mm3, %%mm1            \n\t"
 +
 +        "paddw %%mm2, %%mm5            \n\t"
 +        "paddw %%mm4, %%mm6            \n\t"
 +
 +        "psubusw %%mm3, %%mm1          \n\t"
 +        "psubusw %%mm2, %%mm5          \n\t"
 +
 +        "psubusw %%mm4, %%mm6          \n\t"
 +        "movq %%mm1, %%mm4             \n\t"
 +
 +        "por %%mm5, %%mm4              \n\t"
 +        "paddusw %%mm7, %%mm0          \n\t"
 +
 +        "por %%mm6, %%mm4              \n\t"
 +        "paddw %%mm7, %%mm0            \n\t"
 +
 +        "packssdw %%mm4, %%mm4         \n\t"
 +        "psubusw %%mm7, %%mm0          \n\t"
 +
 +        "movd %%mm4, %%"REG_a"             \n\t"
 +        "or %%"REG_a", %%"REG_a"              \n\t"
 +        "jnz 2f                 \n\t"
 +        //movq [edi+"DCTSIZE_S"*3*2], mm1
 +        //movq [edi+"DCTSIZE_S"*5*2], mm5
 +        //movq [edi+"DCTSIZE_S"*1*2], mm0
 +        //movq [edi+"DCTSIZE_S"*7*2], mm6
 +        // t4 t5 - - - t6 t7 -
 +        //--- t4 (mm0) may be <>0; mm1, mm5, mm6 == 0
 +//Typical numbers: nondc - 19%%,  dc - 26%%,  zero - 55%%. zero case alone isn't worthwhile
 +        "movq 0*8+%3, %%mm4            \n\t"
 +        "movq %%mm0, %%mm1             \n\t"
 +
 +        "pmulhw "MANGLE(MM_FIX_0_847759065)", %%mm0 \n\t" //tmp6
 +        "movq %%mm1, %%mm2             \n\t"
 +
 +        "movq "DCTSIZE_S"*0*2(%%"REG_D"), %%mm5 \n\t"
 +        "movq %%mm2, %%mm3             \n\t"
 +
 +        "pmulhw "MANGLE(MM_FIX_0_566454497)", %%mm1 \n\t" //tmp5
 +        "paddw %%mm4, %%mm5            \n\t"
 +
 +        "movq 1*8+%3, %%mm6            \n\t"
 +        //paddw mm3, MM_2
 +        "psraw $2, %%mm3              \n\t" //tmp7
 +
 +        "pmulhw "MANGLE(MM_FIX_0_198912367)", %%mm2 \n\t" //-tmp4
 +        "psubw %%mm3, %%mm4            \n\t"
 +
 +        "movq "DCTSIZE_S"*1*2(%%"REG_D"), %%mm7 \n\t"
 +        "paddw %%mm3, %%mm5            \n\t"
 +
 +        "movq %%mm4, "DCTSIZE_S"*7*2(%%"REG_D") \n\t"
 +        "paddw %%mm6, %%mm7            \n\t"
 +
 +        "movq 2*8+%3, %%mm3            \n\t"
 +        "psubw %%mm0, %%mm6            \n\t"
 +
 +        "movq "DCTSIZE_S"*2*2(%%"REG_D"), %%mm4 \n\t"
 +        "paddw %%mm0, %%mm7            \n\t"
 +
 +        "movq %%mm5, "DCTSIZE_S"*0*2(%%"REG_D") \n\t"
 +        "paddw %%mm3, %%mm4            \n\t"
 +
 +        "movq %%mm6, "DCTSIZE_S"*6*2(%%"REG_D") \n\t"
 +        "psubw %%mm1, %%mm3            \n\t"
 +
 +        "movq "DCTSIZE_S"*5*2(%%"REG_D"), %%mm5 \n\t"
 +        "paddw %%mm1, %%mm4            \n\t"
 +
 +        "movq "DCTSIZE_S"*3*2(%%"REG_D"), %%mm6 \n\t"
 +        "paddw %%mm3, %%mm5            \n\t"
 +
 +        "movq 3*8+%3, %%mm0            \n\t"
 +        "add $8, %%"REG_S"               \n\t"
 +
 +        "movq %%mm7, "DCTSIZE_S"*1*2(%%"REG_D") \n\t"
 +        "paddw %%mm0, %%mm6            \n\t"
 +
 +        "movq %%mm4, "DCTSIZE_S"*2*2(%%"REG_D") \n\t"
 +        "psubw %%mm2, %%mm0            \n\t"
 +
 +        "movq "DCTSIZE_S"*4*2(%%"REG_D"), %%mm7 \n\t"
 +        "paddw %%mm2, %%mm6            \n\t"
 +
 +        "movq %%mm5, "DCTSIZE_S"*5*2(%%"REG_D") \n\t"
 +        "paddw %%mm0, %%mm7            \n\t"
 +
 +        "movq %%mm6, "DCTSIZE_S"*3*2(%%"REG_D") \n\t"
 +
 +        "movq %%mm7, "DCTSIZE_S"*4*2(%%"REG_D") \n\t"
 +        "add $8, %%"REG_D"               \n\t"
 +        "jmp 4f                  \n\t"
 +
 +        "2:                    \n\t"
 +        //--- non DC2
 +        //psraw mm1, 2 w/o it -> offset. thr1, thr1, thr1  (actually thr1, thr1, thr1-1)
 +        //psraw mm5, 2
 +        //psraw mm0, 2
 +        //psraw mm6, 2
 +        "movq %%mm5, %%mm3             \n\t"
 +        "psubw %%mm1, %%mm5            \n\t"
 +
 +        "psllw $1, %%mm5              \n\t" //'z10
 +        "paddw %%mm1, %%mm3            \n\t" //'z13
 +
 +        "movq %%mm0, %%mm2             \n\t"
 +        "psubw %%mm6, %%mm0            \n\t"
 +
 +        "movq %%mm5, %%mm1             \n\t"
 +        "psllw $1, %%mm0              \n\t" //'z12
 +
 +        "pmulhw "MANGLE(MM_FIX_2_613125930)", %%mm1 \n\t" //-
 +        "paddw %%mm0, %%mm5            \n\t"
 +
 +        "pmulhw "MANGLE(MM_FIX_1_847759065)", %%mm5 \n\t" //'z5
 +        "paddw %%mm6, %%mm2            \n\t" //'z11
 +
 +        "pmulhw "MANGLE(MM_FIX_1_082392200)", %%mm0 \n\t"
 +        "movq %%mm2, %%mm7             \n\t"
 +
 +        //---
 +        "movq 0*8+%3, %%mm4            \n\t"
 +        "psubw %%mm3, %%mm2            \n\t"
 +
 +        "psllw $1, %%mm2              \n\t"
 +        "paddw %%mm3, %%mm7            \n\t" //'t7
 +
 +        "pmulhw "MANGLE(MM_FIX_1_414213562)", %%mm2 \n\t" //'t11
 +        "movq %%mm4, %%mm6             \n\t"
 +        //paddw mm7, MM_2
 +        "psraw $2, %%mm7              \n\t"
 +
 +        "paddw "DCTSIZE_S"*0*2(%%"REG_D"), %%mm4 \n\t"
 +        "psubw %%mm7, %%mm6            \n\t"
 +
 +        "movq 1*8+%3, %%mm3            \n\t"
 +        "paddw %%mm7, %%mm4            \n\t"
 +
 +        "movq %%mm6, "DCTSIZE_S"*7*2(%%"REG_D") \n\t"
 +        "paddw %%mm5, %%mm1            \n\t" //'t12
 +
 +        "movq %%mm4, "DCTSIZE_S"*0*2(%%"REG_D") \n\t"
 +        "psubw %%mm7, %%mm1            \n\t" //'t6
 +
 +        "movq 2*8+%3, %%mm7            \n\t"
 +        "psubw %%mm5, %%mm0            \n\t" //'t10
 +
 +        "movq 3*8+%3, %%mm6            \n\t"
 +        "movq %%mm3, %%mm5             \n\t"
 +
 +        "paddw "DCTSIZE_S"*1*2(%%"REG_D"), %%mm3 \n\t"
 +        "psubw %%mm1, %%mm5            \n\t"
 +
 +        "psubw %%mm1, %%mm2            \n\t" //'t5
 +        "paddw %%mm1, %%mm3            \n\t"
 +
 +        "movq %%mm5, "DCTSIZE_S"*6*2(%%"REG_D") \n\t"
 +        "movq %%mm7, %%mm4             \n\t"
 +
 +        "paddw "DCTSIZE_S"*2*2(%%"REG_D"), %%mm7 \n\t"
 +        "psubw %%mm2, %%mm4            \n\t"
 +
 +        "paddw "DCTSIZE_S"*5*2(%%"REG_D"), %%mm4 \n\t"
 +        "paddw %%mm2, %%mm7            \n\t"
 +
 +        "movq %%mm3, "DCTSIZE_S"*1*2(%%"REG_D") \n\t"
 +        "paddw %%mm2, %%mm0            \n\t" //'t4
 +
 +        // 't4 't6 't5 - - - - 't7
 +        "movq %%mm7, "DCTSIZE_S"*2*2(%%"REG_D") \n\t"
 +        "movq %%mm6, %%mm1             \n\t"
 +
 +        "paddw "DCTSIZE_S"*4*2(%%"REG_D"), %%mm6 \n\t"
 +        "psubw %%mm0, %%mm1            \n\t"
 +
 +        "paddw "DCTSIZE_S"*3*2(%%"REG_D"), %%mm1 \n\t"
 +        "paddw %%mm0, %%mm6            \n\t"
 +
 +        "movq %%mm4, "DCTSIZE_S"*5*2(%%"REG_D") \n\t"
 +        "add $8, %%"REG_S"               \n\t"
 +
 +        "movq %%mm6, "DCTSIZE_S"*4*2(%%"REG_D") \n\t"
 +
 +        "movq %%mm1, "DCTSIZE_S"*3*2(%%"REG_D") \n\t"
 +        "add $8, %%"REG_D"               \n\t"
 +
 +        "4:                     \n\t"
 +//=part 2 (the same)===========================================================
 +        "movq "DCTSIZE_S"*0*2(%%"REG_S"), %%mm1 \n\t"
 +        //
 +        "movq "DCTSIZE_S"*3*2(%%"REG_S"), %%mm7 \n\t"
 +        "movq %%mm1, %%mm0             \n\t"
 +
 +        "paddw "DCTSIZE_S"*7*2(%%"REG_S"), %%mm1 \n\t" //t0
 +        "movq %%mm7, %%mm3             \n\t"
 +
 +        "paddw "DCTSIZE_S"*4*2(%%"REG_S"), %%mm7 \n\t" //t3
 +        "movq %%mm1, %%mm5             \n\t"
 +
 +        "movq "DCTSIZE_S"*1*2(%%"REG_S"), %%mm6 \n\t"
 +        "psubw %%mm7, %%mm1            \n\t" //t13
 +
 +        "movq "DCTSIZE_S"*2*2(%%"REG_S"), %%mm2 \n\t"
 +        "movq %%mm6, %%mm4             \n\t"
 +
 +        "paddw "DCTSIZE_S"*6*2(%%"REG_S"), %%mm6 \n\t" //t1
 +        "paddw %%mm7, %%mm5            \n\t" //t10
 +
 +        "paddw "DCTSIZE_S"*5*2(%%"REG_S"), %%mm2 \n\t" //t2
 +        "movq %%mm6, %%mm7             \n\t"
 +
 +        "paddw %%mm2, %%mm6            \n\t" //t11
 +        "psubw %%mm2, %%mm7            \n\t" //t12
 +
 +        "movq %%mm5, %%mm2             \n\t"
 +        "paddw %%mm6, %%mm5            \n\t" //d0
 +        // i0 t13 t12 i3 i1 d0 - d4
 +        "psubw %%mm6, %%mm2            \n\t" //d4
 +        "paddw %%mm1, %%mm7            \n\t"
 +
 +        "movq  1*8+4*16(%%"REG_d"), %%mm6  \n\t"
 +        "psllw $2, %%mm7              \n\t"
 +
 +        "psubw 1*8+0*16(%%"REG_d"), %%mm5  \n\t"
 +        "psubw %%mm6, %%mm2            \n\t"
 +
 +        "paddusw 1*8+0*16(%%"REG_d"), %%mm5 \n\t"
 +        "paddusw %%mm6, %%mm2          \n\t"
 +
 +        "pmulhw "MANGLE(ff_MM_FIX_0_707106781)", %%mm7 \n\t"
 +        //
 +        "paddw 1*8+0*16(%%"REG_d"), %%mm5  \n\t"
 +        "paddw %%mm6, %%mm2            \n\t"
 +
 +        "psubusw 1*8+0*16(%%"REG_d"), %%mm5 \n\t"
 +        "psubusw %%mm6, %%mm2          \n\t"
 +
 +//This func is totally compute-bound,  operates at huge speed. So,  DC shortcut
 +// at this place isn't worthwhile due to BTB miss penalty (checked on Pent. 3).
 +//However,  typical numbers: nondc - 29%%,  dc - 46%%,  zero - 25%%. All <> 0 case is very rare.
 +        "paddw "MANGLE(MM_2)", %%mm5            \n\t"
 +        "movq %%mm2, %%mm6             \n\t"
 +
 +        "paddw %%mm5, %%mm2            \n\t"
 +        "psubw %%mm6, %%mm5            \n\t"
 +
 +        "movq %%mm1, %%mm6             \n\t"
 +        "paddw %%mm7, %%mm1            \n\t" //d2
 +
 +        "psubw 1*8+2*16(%%"REG_d"), %%mm1  \n\t"
 +        "psubw %%mm7, %%mm6            \n\t" //d6
 +
 +        "movq 1*8+6*16(%%"REG_d"), %%mm7   \n\t"
 +        "psraw $2, %%mm5              \n\t"
 +
 +        "paddusw 1*8+2*16(%%"REG_d"), %%mm1 \n\t"
 +        "psubw %%mm7, %%mm6            \n\t"
 +        // t7 d2 /t11 t4 t6 - d6 /t10
 +
 +        "paddw 1*8+2*16(%%"REG_d"), %%mm1  \n\t"
 +        "paddusw %%mm7, %%mm6          \n\t"
 +
 +        "psubusw 1*8+2*16(%%"REG_d"), %%mm1 \n\t"
 +        "paddw %%mm7, %%mm6            \n\t"
 +
 +        "psubw "DCTSIZE_S"*4*2(%%"REG_S"), %%mm3 \n\t"
 +        "psubusw %%mm7, %%mm6          \n\t"
 +
 +        //movq [edi+"DCTSIZE_S"*2*2], mm1
 +        //movq [edi+"DCTSIZE_S"*6*2], mm6
 +        "movq %%mm1, %%mm7             \n\t"
 +        "psraw $2, %%mm2              \n\t"
 +
 +        "psubw "DCTSIZE_S"*6*2(%%"REG_S"), %%mm4 \n\t"
 +        "psubw %%mm6, %%mm1            \n\t"
 +
 +        "psubw "DCTSIZE_S"*7*2(%%"REG_S"), %%mm0 \n\t"
 +        "paddw %%mm7, %%mm6            \n\t" //'t13
 +
 +        "psraw $2, %%mm6              \n\t" //paddw mm6, MM_2 !!    ---
 +        "movq %%mm2, %%mm7             \n\t"
 +
 +        "pmulhw "MANGLE(MM_FIX_1_414213562_A)", %%mm1 \n\t"
 +        "paddw %%mm6, %%mm2            \n\t" //'t0
 +
 +        "movq %%mm2, 0*8+%3            \n\t" //!
 +        "psubw %%mm6, %%mm7            \n\t" //'t3
 +
 +        "movq "DCTSIZE_S"*2*2(%%"REG_S"), %%mm2 \n\t"
 +        "psubw %%mm6, %%mm1            \n\t" //'t12
 +
 +        "psubw "DCTSIZE_S"*5*2(%%"REG_S"), %%mm2 \n\t" //t5
 +        "movq %%mm5, %%mm6             \n\t"
 +
 +        "movq %%mm7, 3*8+%3            \n\t"
 +        "paddw %%mm2, %%mm3            \n\t" //t10
 +
 +        "paddw %%mm4, %%mm2            \n\t" //t11
 +        "paddw %%mm0, %%mm4            \n\t" //t12
 +
 +        "movq %%mm3, %%mm7             \n\t"
 +        "psubw %%mm4, %%mm3            \n\t"
 +
 +        "psllw $2, %%mm3              \n\t"
 +        "psllw $2, %%mm7              \n\t" //opt for P6
 +
 +        "pmulhw "MANGLE(MM_FIX_0_382683433)", %%mm3 \n\t"
 +        "psllw $2, %%mm4              \n\t"
 +
 +        "pmulhw "MANGLE(ff_MM_FIX_0_541196100)", %%mm7 \n\t"
 +        "psllw $2, %%mm2              \n\t"