Merge commit 'a9aee08d900f686e966c64afec5d88a7d9d130a3'
authorMichael Niedermayer <michaelni@gmx.at>
Tue, 8 Jul 2014 01:12:10 +0000 (03:12 +0200)
committerMichael Niedermayer <michaelni@gmx.at>
Tue, 8 Jul 2014 01:19:06 +0000 (03:19 +0200)
* commit 'a9aee08d900f686e966c64afec5d88a7d9d130a3':
  dsputil: Split off FDCT bits into their own context

Conflicts:
configure
libavcodec/Makefile
libavcodec/asvenc.c
libavcodec/dnxhdenc.c
libavcodec/dsputil.c
libavcodec/mpegvideo.h
libavcodec/mpegvideo_enc.c
libavcodec/x86/Makefile
libavcodec/x86/dsputilenc_mmx.c

Merged-by: Michael Niedermayer <michaelni@gmx.at>
25 files changed:
1  2 
configure
libavcodec/Makefile
libavcodec/asv.h
libavcodec/asvenc.c
libavcodec/dnxhdenc.c
libavcodec/dsputil.c
libavcodec/dsputil.h
libavcodec/dvenc.c
libavcodec/fdctdsp.c
libavcodec/fdctdsp.h
libavcodec/libavcodec.v
libavcodec/mpegvideo.h
libavcodec/mpegvideo_enc.c
libavcodec/ppc/Makefile
libavcodec/ppc/dsputil_altivec.h
libavcodec/ppc/dsputil_ppc.c
libavcodec/ppc/fdctdsp.c
libavcodec/ppc/fdctdsp.h
libavcodec/proresenc_anatoliy.c
libavcodec/proresenc_kostya.c
libavcodec/x86/Makefile
libavcodec/x86/dsputilenc_mmx.c
libavcodec/x86/fdctdsp_init.c
libavfilter/vf_spp.c
libavfilter/vf_spp.h

diff --cc configure
+++ b/configure
@@@ -1801,8 -1534,7 +1801,9 @@@ CONFIG_EXTRA=
      bswapdsp
      cabac
      dsputil
 +    exif
+     fdctdsp
 +    frame_thread_encoder
      gcrypt
      golomb
      gplv3
@@@ -1995,9 -1705,8 +1996,9 @@@ threads_if_any="$THREADS_LIST
  
  # subsystems
  dct_select="rdft"
- dsputil_select="idctdsp"
+ dsputil_select="fdctdsp idctdsp"
  error_resilience_select="dsputil"
 +frame_thread_encoder_deps="encoders threads"
  intrax8_select="error_resilience"
  mdct_select="fft"
  rdft_select="fft"
@@@ -2020,13 -1728,12 +2021,13 @@@ alac_encoder_select="lpc
  als_decoder_select="bswapdsp"
  amrnb_decoder_select="lsp"
  amrwb_decoder_select="lsp"
 -amv_decoder_select="sp5x_decoder"
 -ape_decoder_select="bswapdsp"
 +amv_decoder_select="sp5x_decoder exif"
 +amv_encoder_select="aandcttables mpegvideoenc"
 +ape_decoder_select="bswapdsp llauddsp"
  asv1_decoder_select="blockdsp bswapdsp idctdsp"
- asv1_encoder_select="bswapdsp dsputil"
+ asv1_encoder_select="bswapdsp dsputil fdctdsp"
  asv2_decoder_select="blockdsp bswapdsp idctdsp"
- asv2_encoder_select="bswapdsp dsputil"
+ asv2_encoder_select="bswapdsp dsputil fdctdsp"
  atrac1_decoder_select="mdct sinewin"
  atrac3_decoder_select="mdct"
  atrac3p_decoder_select="mdct sinewin"
@@@ -2041,12 -1747,11 +2042,12 @@@ cook_decoder_select="audiodsp mdct sine
  cscd_decoder_select="lzo"
  cscd_decoder_suggest="zlib"
  dca_decoder_select="mdct"
 +dirac_decoder_select="dsputil dwt golomb videodsp"
  dnxhd_decoder_select="blockdsp idctdsp"
- dnxhd_encoder_select="aandcttables blockdsp dsputil idctdsp mpegvideoenc"
+ dnxhd_encoder_select="aandcttables blockdsp dsputil fdctdsp idctdsp mpegvideoenc"
  dvvideo_decoder_select="idctdsp"
- dvvideo_encoder_select="dsputil"
+ dvvideo_encoder_select="dsputil fdctdsp"
 -dxa_decoder_deps="zlib"
 +dxa_decoder_select="zlib"
  eac3_decoder_select="ac3_decoder"
  eac3_encoder_select="ac3_encoder"
  eamad_decoder_select="aandcttables blockdsp bswapdsp idctdsp mpegvideo"
@@@ -2130,18 -1834,16 +2131,18 @@@ nellymoser_decoder_select="mdct sinewin
  nellymoser_encoder_select="audio_frame_queue mdct sinewin"
  nuv_decoder_select="idctdsp lzo"
  on2avc_decoder_select="mdct"
 -opus_decoder_deps="avresample"
 -png_decoder_deps="zlib"
 -png_encoder_deps="zlib"
 -png_encoder_select="huffyuvencdsp"
 -prores_decoder_select="idctdsp"
 +opus_decoder_deps="swresample"
 +png_decoder_select="zlib"
 +png_encoder_select="huffyuvencdsp zlib"
 +prores_decoder_select="blockdsp idctdsp"
- prores_encoder_select="dsputil"
+ prores_encoder_select="fdctdsp"
  qcelp_decoder_select="lsp"
  qdm2_decoder_select="mdct rdft mpegaudiodsp"
 -ra_144_encoder_select="audio_frame_queue lpc"
 +ra_144_encoder_select="audio_frame_queue lpc audiodsp"
 +ra_144_decoder_select="audiodsp"
  ralf_decoder_select="golomb"
 +rawvideo_decoder_select="dsputil"
 +rtjpeg_decoder_select="dsputil"
  rv10_decoder_select="error_resilience h263_decoder h263dsp mpeg_er"
  rv10_encoder_select="h263_encoder"
  rv20_decoder_select="error_resilience h263_decoder h263dsp mpeg_er"
@@@ -41,12 -35,11 +41,13 @@@ OBJS-$(CONFIG_CRYSTALHD)               
  OBJS-$(CONFIG_DCT)                     += dct.o dct32_fixed.o dct32_float.o
  OBJS-$(CONFIG_DSPUTIL)                 += dsputil.o
  OBJS-$(CONFIG_DXVA2)                   += dxva2.o
- OBJS-$(CONFIG_ENCODERS)                += faandct.o jfdctfst.o jfdctint.o
  OBJS-$(CONFIG_ERROR_RESILIENCE)        += error_resilience.o
 +OBJS-$(CONFIG_EXIF)                    += exif.o tiff_common.o
+ OBJS-$(CONFIG_FDCTDSP)                 += fdctdsp.o faandct.o           \
+                                           jfdctfst.o jfdctint.o
  FFT-OBJS-$(CONFIG_HARDCODED_TABLES)    += cos_tables.o cos_fixed_tables.o
  OBJS-$(CONFIG_FFT)                     += avfft.o fft_fixed.o fft_float.o \
 +                                          fft_fixed_32.o fft_init_table.o \
                                            $(FFT-OBJS-yes)
  OBJS-$(CONFIG_GOLOMB)                  += golomb.o
  OBJS-$(CONFIG_H263DSP)                 += h263dsp.o
Simple merge
@@@ -28,7 -28,7 +28,8 @@@
  
  #include "asv.h"
  #include "avcodec.h"
+ #include "fdctdsp.h"
 +#include "internal.h"
  #include "mathops.h"
  #include "mpeg12data.h"
  
@@@ -280,10 -241,17 +281,11 @@@ static av_cold int encode_init(AVCodecC
      int i;
      const int scale= avctx->codec_id == AV_CODEC_ID_ASV1 ? 1 : 2;
  
 -    avctx->coded_frame = av_frame_alloc();
 -    if (!avctx->coded_frame)
 -        return AVERROR(ENOMEM);
 -    avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I;
 -    avctx->coded_frame->key_frame = 1;
 -
      ff_asv_common_init(avctx);
      ff_dsputil_init(&a->dsp, avctx);
+     ff_fdctdsp_init(&a->fdsp, avctx);
  
 -    if(avctx->global_quality == 0) avctx->global_quality= 4*FF_QUALITY_SCALE;
 +    if(avctx->global_quality <= 0) avctx->global_quality= 4*FF_QUALITY_SCALE;
  
      a->inv_qscale= (32*scale*FF_QUALITY_SCALE +  avctx->global_quality/2) / avctx->global_quality;
  
@@@ -322,6 -308,8 +323,7 @@@ static av_cold int dnxhd_encode_init(AV
      avctx->bits_per_raw_sample = ctx->cid_table->bit_depth;
  
      ff_blockdsp_init(&ctx->bdsp, avctx);
 -    ff_dsputil_init(&ctx->m.dsp, avctx);
+     ff_fdctdsp_init(&ctx->m.fdsp, avctx);
      ff_idctdsp_init(&ctx->m.idsp, avctx);
      ff_mpegvideoencdsp_init(&ctx->m.mpvencdsp, avctx);
      ff_dct_common_init(&ctx->m);
   */
  
  #include "libavutil/attributes.h"
 +#include "libavutil/internal.h"
  #include "avcodec.h"
  #include "copy_block.h"
- #include "dct.h"
  #include "dsputil.h"
  #include "simple_idct.h"
- #include "faandct.h"
  #include "mpegvideo.h"
  #include "config.h"
  
@@@ -586,10 -575,10 +584,10 @@@ static int dct_sad8x8_c(MpegEncContext 
  {
      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);
+     s->fdsp.fdct(temp);
      return s->dsp.sum_abs_dctelem(temp);
  }
  
@@@ -653,10 -642,10 +651,10 @@@ static int dct_max8x8_c(MpegEncContext 
      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);
+     s->fdsp.fdct(temp);
  
      for (i = 0; i < 64; i++)
          sum = FFMAX(sum, FFABS(temp[i]));
@@@ -971,26 -932,6 +969,8 @@@ av_cold void ff_dsputil_init(DSPContex
  {
      const unsigned high_bit_depth = avctx->bits_per_raw_sample > 8;
  
- #if CONFIG_ENCODERS
-     if (avctx->bits_per_raw_sample == 10) {
-         c->fdct    = ff_jpeg_fdct_islow_10;
-         c->fdct248 = ff_fdct248_islow_10;
-     } else {
-         if (avctx->dct_algo == FF_DCT_FASTINT) {
-             c->fdct    = ff_fdct_ifast;
-             c->fdct248 = ff_fdct_ifast248;
-         } else if (avctx->dct_algo == FF_DCT_FAAN) {
-             c->fdct    = ff_faandct;
-             c->fdct248 = ff_faandct248;
-         } else {
-             c->fdct    = ff_jpeg_fdct_islow_8; // slow/accurate/default
-             c->fdct248 = ff_fdct248_islow_8;
-         }
-     }
- #endif /* CONFIG_ENCODERS */
 +    ff_check_alignment();
 +
      c->diff_pixels = diff_pixels_c;
  
      c->sum_abs_dctelem = sum_abs_dctelem_c;
Simple merge
@@@ -64,8 -62,8 +66,9 @@@ static av_cold int dvvideo_encode_init(
  
      dv_vlc_map_tableinit();
  
 +    memset(&dsp,0, sizeof(dsp));
      ff_dsputil_init(&dsp, avctx);
+     ff_fdctdsp_init(&fdsp, avctx);
      ff_set_cmp(&dsp, dsp.ildct_cmp, avctx->ildct_cmp);
  
      s->get_pixels = dsp.get_pixels;
index 0000000,b245198..f75eed5
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,50 +1,50 @@@
 - * This file is part of Libav.
+ /*
 - * Libav is free software; you can redistribute it and/or
++ * This file is part of FFmpeg.
+  *
 - * Libav is distributed in the hope that it will be useful,
++ * FFmpeg is free software; you can redistribute it and/or
+  * modify it under the terms of the GNU Lesser General Public
+  * License as published by the Free Software Foundation; either
+  * version 2.1 of the License, or (at your option) any later version.
+  *
 - * License along with Libav; if not, write to the Free Software
++ * FFmpeg is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  * Lesser General Public License for more details.
+  *
+  * You should have received a copy of the GNU Lesser General Public
++ * License along with FFmpeg; if not, write to the Free Software
+  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+  */
+ #include "libavutil/attributes.h"
+ #include "avcodec.h"
+ #include "dct.h"
+ #include "faandct.h"
+ #include "fdctdsp.h"
+ #include "config.h"
+ av_cold void ff_fdctdsp_init(FDCTDSPContext *c, AVCodecContext *avctx)
+ {
+     const unsigned high_bit_depth = avctx->bits_per_raw_sample > 8;
+     if (avctx->bits_per_raw_sample == 10) {
+         c->fdct    = ff_jpeg_fdct_islow_10;
+         c->fdct248 = ff_fdct248_islow_10;
+     } else {
+         if (avctx->dct_algo == FF_DCT_FASTINT) {
+             c->fdct    = ff_fdct_ifast;
+             c->fdct248 = ff_fdct_ifast248;
+         } else if (avctx->dct_algo == FF_DCT_FAAN) {
+             c->fdct    = ff_faandct;
+             c->fdct248 = ff_faandct248;
+         } else {
+             c->fdct    = ff_jpeg_fdct_islow_8; // slow/accurate/default
+             c->fdct248 = ff_fdct248_islow_8;
+         }
+     }
+     if (ARCH_PPC)
+         ff_fdctdsp_init_ppc(c, avctx, high_bit_depth);
+     if (ARCH_X86)
+         ff_fdctdsp_init_x86(c, avctx, high_bit_depth);
+ }
index 0000000,944dc6d..3e1f683
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,37 +1,37 @@@
 - * This file is part of Libav.
+ /*
 - * Libav is free software; you can redistribute it and/or
++ * This file is part of FFmpeg.
+  *
 - * Libav is distributed in the hope that it will be useful,
++ * FFmpeg is free software; you can redistribute it and/or
+  * modify it under the terms of the GNU Lesser General Public
+  * License as published by the Free Software Foundation; either
+  * version 2.1 of the License, or (at your option) any later version.
+  *
 - * License along with Libav; if not, write to the Free Software
++ * FFmpeg is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  * Lesser General Public License for more details.
+  *
+  * You should have received a copy of the GNU Lesser General Public
++ * License along with FFmpeg; if not, write to the Free Software
+  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+  */
+ #ifndef AVCODEC_FDCTDSP_H
+ #define AVCODEC_FDCTDSP_H
+ #include <stdint.h>
+ #include "avcodec.h"
+ typedef struct FDCTDSPContext {
+     void (*fdct)(int16_t *block /* align 16 */);
+     void (*fdct248)(int16_t *block /* align 16 */);
+ } FDCTDSPContext;
+ void ff_fdctdsp_init(FDCTDSPContext *c, AVCodecContext *avctx);
+ void ff_fdctdsp_init_ppc(FDCTDSPContext *c, AVCodecContext *avctx,
+                          unsigned high_bit_depth);
+ void ff_fdctdsp_init_x86(FDCTDSPContext *c, AVCodecContext *avctx,
+                          unsigned high_bit_depth);
+ #endif /* AVCODEC_FDCTDSP_H */
@@@ -1,32 -1,4 +1,33 @@@
  LIBAVCODEC_$MAJOR {
          global: av*;
 +                #deprecated, remove after next bump
 +                audio_resample;
 +                audio_resample_close;
 +                dsputil_init;
 +                ff_dsputil_init;
 +                ff_find_pix_fmt;
 +                ff_framenum_to_drop_timecode;
 +                ff_framenum_to_smtpe_timecode;
 +                ff_raw_pix_fmt_tags;
 +                ff_init_smtpe_timecode;
 +                ff_fft*;
 +                ff_mdct*;
 +                ff_dct*;
 +                ff_rdft*;
 +                ff_prores_idct_put_10_sse2;
 +                ff_simple_idct*;
 +                ff_aanscales;
 +                ff_faan*;
 +                ff_mmx_idct;
 +                ff_fdct*;
 +                fdct_ifast;
 +                j_rev_dct;
 +                ff_mmxext_idct;
 +                ff_idct_xvid*;
 +                ff_jpeg_fdct*;
 +                ff_dnxhd_get_cid_table;
 +                ff_dnxhd_cid_table;
 +                ff_idctdsp_init;
++                ff_fdctdsp_init;
          local:  *;
  };
@@@ -32,8 -32,8 +32,9 @@@
  #include "blockdsp.h"
  #include "dsputil.h"
  #include "error_resilience.h"
+ #include "fdctdsp.h"
  #include "get_bits.h"
 +#include "h264chroma.h"
  #include "h263dsp.h"
  #include "hpeldsp.h"
  #include "idctdsp.h"
@@@ -364,7 -356,7 +365,8 @@@ typedef struct MpegEncContext 
  
      BlockDSPContext bdsp;
      DSPContext dsp;             ///< pointers for accelerated dsp functions
+     FDCTDSPContext fdsp;
 +    H264ChromaContext h264chroma;
      HpelDSPContext hdsp;
      IDCTDSPContext idsp;
      MpegVideoDSPContext mdsp;
@@@ -818,6 -698,10 +818,7 @@@ av_cold int ff_MPV_encode_init(AVCodecC
      if (ff_MPV_common_init(s) < 0)
          return -1;
  
 -    if (ARCH_X86)
 -        ff_MPV_encode_init_x86(s);
 -
+     ff_fdctdsp_init(&s->fdsp, avctx);
      ff_mpegvideoencdsp_init(&s->mpvencdsp, avctx);
      ff_qpeldsp_init(&s->qdsp);
  
@@@ -25,8 -26,6 +26,7 @@@ OBJS-$(CONFIG_VP7_DECODER)             
  OBJS-$(CONFIG_VP8_DECODER)             += ppc/vp8dsp_altivec.o
  
  ALTIVEC-OBJS-$(CONFIG_DSPUTIL)         += ppc/dsputil_altivec.o         \
-                                           ppc/fdct_altivec.o            \
  
  FFT-OBJS-$(HAVE_GNU_AS)                += ppc/fft_altivec_s.o
 +FFT-OBJS-$(HAVE_VSX)                   += ppc/fft_vsx.o
  ALTIVEC-OBJS-$(CONFIG_FFT)             += $(FFT-OBJS-yes)
Simple merge
  av_cold void ff_dsputil_init_ppc(DSPContext *c, AVCodecContext *avctx,
                                   unsigned high_bit_depth)
  {
 -    if (PPC_ALTIVEC(av_get_cpu_flags())) {
 +    int mm_flags = av_get_cpu_flags();
 +    if (PPC_ALTIVEC(mm_flags)) {
          ff_dsputil_init_altivec(c, avctx, high_bit_depth);
-         if (!high_bit_depth) {
- #if CONFIG_ENCODERS
-             if (avctx->dct_algo == FF_DCT_AUTO ||
-                 avctx->dct_algo == FF_DCT_ALTIVEC) {
-                 c->fdct = ff_fdct_altivec;
-             }
- #endif //CONFIG_ENCODERS
-         }
      }
  }
index 0000000,d7b5b7a..561e469
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,479 +1,479 @@@
 - * This file is part of Libav.
+ /*
+  * Copyright (C) 2003  James Klicman <james@klicman.org>
+  *
 - * Libav is free software; you can redistribute it and/or
++ * This file is part of FFmpeg.
+  *
 - * Libav is distributed in the hope that it will be useful,
++ * FFmpeg is free software; you can redistribute it and/or
+  * modify it under the terms of the GNU Lesser General Public
+  * License as published by the Free Software Foundation; either
+  * version 2.1 of the License, or (at your option) any later version.
+  *
 - * License along with Libav; if not, write to the Free Software
++ * FFmpeg is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  * Lesser General Public License for more details.
+  *
+  * You should have received a copy of the GNU Lesser General Public
++ * License along with FFmpeg; if not, write to the Free Software
+  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+  */
+ #include "config.h"
+ #if HAVE_ALTIVEC_H
+ #include <altivec.h>
+ #endif
+ #include "libavutil/attributes.h"
+ #include "libavutil/cpu.h"
+ #include "libavutil/ppc/cpu.h"
+ #include "libavcodec/fdctdsp.h"
+ #include "fdctdsp.h"
+ #if HAVE_ALTIVEC
+ #define vs16(v)   ((vector signed short) (v))
+ #define vs32(v)     ((vector signed int) (v))
+ #define  vu8(v)  ((vector unsigned char) (v))
+ #define vu16(v) ((vector unsigned short) (v))
+ #define vu32(v)   ((vector unsigned int) (v))
+ #define C1     0.98078525066375732421875000 /* cos(1 * PI / 16) */
+ #define C2     0.92387950420379638671875000 /* cos(2 * PI / 16) */
+ #define C3     0.83146959543228149414062500 /* cos(3 * PI / 16) */
+ #define C4     0.70710676908493041992187500 /* cos(4 * PI / 16) */
+ #define C5     0.55557024478912353515625000 /* cos(5 * PI / 16) */
+ #define C6     0.38268342614173889160156250 /* cos(6 * PI / 16) */
+ #define C7     0.19509032368659973144531250 /* cos(7 * PI / 16) */
+ #define SQRT_2 1.41421353816986083984375000 /* sqrt(2)          */
+ #define W0 -(2 * C2)
+ #define W1  (2 * C6)
+ #define W2 (SQRT_2 * C6)
+ #define W3 (SQRT_2 * C3)
+ #define W4 (SQRT_2 * (-C1 + C3 + C5 - C7))
+ #define W5 (SQRT_2 *  (C1 + C3 - C5 + C7))
+ #define W6 (SQRT_2 *  (C1 + C3 + C5 - C7))
+ #define W7 (SQRT_2 *  (C1 + C3 - C5 - C7))
+ #define W8 (SQRT_2 *  (C7 - C3))
+ #define W9 (SQRT_2 * (-C1 - C3))
+ #define WA (SQRT_2 * (-C3 - C5))
+ #define WB (SQRT_2 *  (C5 - C3))
+ static vector float fdctconsts[3] = {
+     { W0, W1, W2, W3 },
+     { W4, W5, W6, W7 },
+     { W8, W9, WA, WB }
+ };
+ #define LD_W0 vec_splat(cnsts0, 0)
+ #define LD_W1 vec_splat(cnsts0, 1)
+ #define LD_W2 vec_splat(cnsts0, 2)
+ #define LD_W3 vec_splat(cnsts0, 3)
+ #define LD_W4 vec_splat(cnsts1, 0)
+ #define LD_W5 vec_splat(cnsts1, 1)
+ #define LD_W6 vec_splat(cnsts1, 2)
+ #define LD_W7 vec_splat(cnsts1, 3)
+ #define LD_W8 vec_splat(cnsts2, 0)
+ #define LD_W9 vec_splat(cnsts2, 1)
+ #define LD_WA vec_splat(cnsts2, 2)
+ #define LD_WB vec_splat(cnsts2, 3)
+ #define FDCTROW(b0, b1, b2, b3, b4, b5, b6, b7) /* {{{ */           \
+     x0 = vec_add(b0, b7);               /* x0 = b0 + b7; */         \
+     x7 = vec_sub(b0, b7);               /* x7 = b0 - b7; */         \
+     x1 = vec_add(b1, b6);               /* x1 = b1 + b6; */         \
+     x6 = vec_sub(b1, b6);               /* x6 = b1 - b6; */         \
+     x2 = vec_add(b2, b5);               /* x2 = b2 + b5; */         \
+     x5 = vec_sub(b2, b5);               /* x5 = b2 - b5; */         \
+     x3 = vec_add(b3, b4);               /* x3 = b3 + b4; */         \
+     x4 = vec_sub(b3, b4);               /* x4 = b3 - b4; */         \
+                                                                     \
+     b7 = vec_add(x0, x3);               /* b7 = x0 + x3; */         \
+     b1 = vec_add(x1, x2);               /* b1 = x1 + x2; */         \
+     b0 = vec_add(b7, b1);               /* b0 = b7 + b1; */         \
+     b4 = vec_sub(b7, b1);               /* b4 = b7 - b1; */         \
+                                                                     \
+     b2   = vec_sub(x0, x3);             /* b2 = x0 - x3; */         \
+     b6   = vec_sub(x1, x2);             /* b6 = x1 - x2; */         \
+     b5   = vec_add(b6, b2);             /* b5 = b6 + b2; */         \
+     cnst = LD_W2;                                                   \
+     b5   = vec_madd(cnst, b5, mzero);   /* b5 = b5 * W2; */         \
+     cnst = LD_W1;                                                   \
+     b2   = vec_madd(cnst, b2, b5);      /* b2 = b5 + b2 * W1; */    \
+     cnst = LD_W0;                                                   \
+     b6   = vec_madd(cnst, b6, b5);      /* b6 = b5 + b6 * W0; */    \
+                                                                     \
+     x0   = vec_add(x4, x7);             /* x0 = x4 + x7; */         \
+     x1   = vec_add(x5, x6);             /* x1 = x5 + x6; */         \
+     x2   = vec_add(x4, x6);             /* x2 = x4 + x6; */         \
+     x3   = vec_add(x5, x7);             /* x3 = x5 + x7; */         \
+     x8   = vec_add(x2, x3);             /* x8 = x2 + x3; */         \
+     cnst = LD_W3;                                                   \
+     x8   = vec_madd(cnst, x8, mzero);   /* x8 = x8 * W3; */         \
+                                                                     \
+     cnst = LD_W8;                                                   \
+     x0   = vec_madd(cnst, x0, mzero);   /* x0 *= W8; */             \
+     cnst = LD_W9;                                                   \
+     x1   = vec_madd(cnst, x1, mzero);   /* x1 *= W9; */             \
+     cnst = LD_WA;                                                   \
+     x2   = vec_madd(cnst, x2, x8);      /* x2 = x2 * WA + x8; */    \
+     cnst = LD_WB;                                                   \
+     x3   = vec_madd(cnst, x3, x8);      /* x3 = x3 * WB + x8; */    \
+                                                                     \
+     cnst = LD_W4;                                                   \
+     b7   = vec_madd(cnst, x4, x0);      /* b7 = x4 * W4 + x0; */    \
+     cnst = LD_W5;                                                   \
+     b5   = vec_madd(cnst, x5, x1);      /* b5 = x5 * W5 + x1; */    \
+     cnst = LD_W6;                                                   \
+     b3   = vec_madd(cnst, x6, x1);      /* b3 = x6 * W6 + x1; */    \
+     cnst = LD_W7;                                                   \
+     b1   = vec_madd(cnst, x7, x0);      /* b1 = x7 * W7 + x0; */    \
+                                                                     \
+     b7 = vec_add(b7, x2);               /* b7 = b7 + x2; */         \
+     b5 = vec_add(b5, x3);               /* b5 = b5 + x3; */         \
+     b3 = vec_add(b3, x2);               /* b3 = b3 + x2; */         \
+     b1 = vec_add(b1, x3)                /* b1 = b1 + x3; */         \
+     /* }}} */
+ #define FDCTCOL(b0, b1, b2, b3, b4, b5, b6, b7) /* {{{ */           \
+     x0 = vec_add(b0, b7);               /* x0 = b0 + b7; */         \
+     x7 = vec_sub(b0, b7);               /* x7 = b0 - b7; */         \
+     x1 = vec_add(b1, b6);               /* x1 = b1 + b6; */         \
+     x6 = vec_sub(b1, b6);               /* x6 = b1 - b6; */         \
+     x2 = vec_add(b2, b5);               /* x2 = b2 + b5; */         \
+     x5 = vec_sub(b2, b5);               /* x5 = b2 - b5; */         \
+     x3 = vec_add(b3, b4);               /* x3 = b3 + b4; */         \
+     x4 = vec_sub(b3, b4);               /* x4 = b3 - b4; */         \
+                                                                     \
+     b7 = vec_add(x0, x3);               /* b7 = x0 + x3; */         \
+     b1 = vec_add(x1, x2);               /* b1 = x1 + x2; */         \
+     b0 = vec_add(b7, b1);               /* b0 = b7 + b1; */         \
+     b4 = vec_sub(b7, b1);               /* b4 = b7 - b1; */         \
+                                                                     \
+     b2   = vec_sub(x0, x3);             /* b2 = x0 - x3; */         \
+     b6   = vec_sub(x1, x2);             /* b6 = x1 - x2; */         \
+     b5   = vec_add(b6, b2);             /* b5 = b6 + b2; */         \
+     cnst = LD_W2;                                                   \
+     b5   = vec_madd(cnst, b5, mzero);   /* b5 = b5 * W2; */         \
+     cnst = LD_W1;                                                   \
+     b2   = vec_madd(cnst, b2, b5);      /* b2 = b5 + b2 * W1; */    \
+     cnst = LD_W0;                                                   \
+     b6   = vec_madd(cnst, b6, b5);      /* b6 = b5 + b6 * W0; */    \
+                                                                     \
+     x0   = vec_add(x4, x7);             /* x0 = x4 + x7; */         \
+     x1   = vec_add(x5, x6);             /* x1 = x5 + x6; */         \
+     x2   = vec_add(x4, x6);             /* x2 = x4 + x6; */         \
+     x3   = vec_add(x5, x7);             /* x3 = x5 + x7; */         \
+     x8   = vec_add(x2, x3);             /* x8 = x2 + x3; */         \
+     cnst = LD_W3;                                                   \
+     x8   = vec_madd(cnst, x8, mzero);   /* x8 = x8 * W3; */         \
+                                                                     \
+     cnst = LD_W8;                                                   \
+     x0   = vec_madd(cnst, x0, mzero);   /* x0 *= W8; */             \
+     cnst = LD_W9;                                                   \
+     x1   = vec_madd(cnst, x1, mzero);   /* x1 *= W9; */             \
+     cnst = LD_WA;                                                   \
+     x2   = vec_madd(cnst, x2, x8);      /* x2 = x2 * WA + x8; */    \
+     cnst = LD_WB;                                                   \
+     x3   = vec_madd(cnst, x3, x8);      /* x3 = x3 * WB + x8; */    \
+                                                                     \
+     cnst = LD_W4;                                                   \
+     b7   = vec_madd(cnst, x4, x0);      /* b7 = x4 * W4 + x0; */    \
+     cnst = LD_W5;                                                   \
+     b5   = vec_madd(cnst, x5, x1);      /* b5 = x5 * W5 + x1; */    \
+     cnst = LD_W6;                                                   \
+     b3   = vec_madd(cnst, x6, x1);      /* b3 = x6 * W6 + x1; */    \
+     cnst = LD_W7;                                                   \
+     b1   = vec_madd(cnst, x7, x0);      /* b1 = x7 * W7 + x0; */    \
+                                                                     \
+     b7 = vec_add(b7, x2);               /* b7 += x2; */             \
+     b5 = vec_add(b5, x3);               /* b5 += x3; */             \
+     b3 = vec_add(b3, x2);               /* b3 += x2; */             \
+     b1 = vec_add(b1, x3)                /* b1 += x3; */             \
+     /* }}} */
+ /* two dimensional discrete cosine transform */
+ void ff_fdct_altivec(int16_t *block)
+ {
+     vector signed short *bp;
+     vector float *cp = fdctconsts;
+     vector float b00, b10, b20, b30, b40, b50, b60, b70;
+     vector float b01, b11, b21, b31, b41, b51, b61, b71;
+     vector float mzero, cnst, cnsts0, cnsts1, cnsts2;
+     vector float x0, x1, x2, x3, x4, x5, x6, x7, x8;
+     /* setup constants {{{ */
+     /* mzero = -0.0 */
+     mzero  = ((vector float) vec_splat_u32(-1));
+     mzero  = ((vector float) vec_sl(vu32(mzero), vu32(mzero)));
+     cnsts0 = vec_ld(0, cp);
+     cp++;
+     cnsts1 = vec_ld(0, cp);
+     cp++;
+     cnsts2 = vec_ld(0, cp);
+     /* }}} */
+     /* 8x8 matrix transpose (vector short[8]) {{{ */
+ #define MERGE_S16(hl, a, b) vec_merge ## hl(vs16(a), vs16(b))
+     bp  = (vector signed short *) block;
+     b00 = ((vector float) vec_ld(0,      bp));
+     b40 = ((vector float) vec_ld(16 * 4, bp));
+     b01 = ((vector float) MERGE_S16(h, b00, b40));
+     b11 = ((vector float) MERGE_S16(l, b00, b40));
+     bp++;
+     b10 = ((vector float) vec_ld(0,      bp));
+     b50 = ((vector float) vec_ld(16 * 4, bp));
+     b21 = ((vector float) MERGE_S16(h, b10, b50));
+     b31 = ((vector float) MERGE_S16(l, b10, b50));
+     bp++;
+     b20 = ((vector float) vec_ld(0,      bp));
+     b60 = ((vector float) vec_ld(16 * 4, bp));
+     b41 = ((vector float) MERGE_S16(h, b20, b60));
+     b51 = ((vector float) MERGE_S16(l, b20, b60));
+     bp++;
+     b30 = ((vector float) vec_ld(0,      bp));
+     b70 = ((vector float) vec_ld(16 * 4, bp));
+     b61 = ((vector float) MERGE_S16(h, b30, b70));
+     b71 = ((vector float) MERGE_S16(l, b30, b70));
+     x0 = ((vector float) MERGE_S16(h, b01, b41));
+     x1 = ((vector float) MERGE_S16(l, b01, b41));
+     x2 = ((vector float) MERGE_S16(h, b11, b51));
+     x3 = ((vector float) MERGE_S16(l, b11, b51));
+     x4 = ((vector float) MERGE_S16(h, b21, b61));
+     x5 = ((vector float) MERGE_S16(l, b21, b61));
+     x6 = ((vector float) MERGE_S16(h, b31, b71));
+     x7 = ((vector float) MERGE_S16(l, b31, b71));
+     b00 = ((vector float) MERGE_S16(h, x0, x4));
+     b10 = ((vector float) MERGE_S16(l, x0, x4));
+     b20 = ((vector float) MERGE_S16(h, x1, x5));
+     b30 = ((vector float) MERGE_S16(l, x1, x5));
+     b40 = ((vector float) MERGE_S16(h, x2, x6));
+     b50 = ((vector float) MERGE_S16(l, x2, x6));
+     b60 = ((vector float) MERGE_S16(h, x3, x7));
+     b70 = ((vector float) MERGE_S16(l, x3, x7));
+ #undef MERGE_S16
+     /* }}} */
+     /* Some of the initial calculations can be done as vector short
+      * before conversion to vector float.  The following code section
+      * takes advantage of this. */
+     /* fdct rows {{{ */
+     x0 = ((vector float) vec_add(vs16(b00), vs16(b70)));
+     x7 = ((vector float) vec_sub(vs16(b00), vs16(b70)));
+     x1 = ((vector float) vec_add(vs16(b10), vs16(b60)));
+     x6 = ((vector float) vec_sub(vs16(b10), vs16(b60)));
+     x2 = ((vector float) vec_add(vs16(b20), vs16(b50)));
+     x5 = ((vector float) vec_sub(vs16(b20), vs16(b50)));
+     x3 = ((vector float) vec_add(vs16(b30), vs16(b40)));
+     x4 = ((vector float) vec_sub(vs16(b30), vs16(b40)));
+     b70 = ((vector float) vec_add(vs16(x0), vs16(x3)));
+     b10 = ((vector float) vec_add(vs16(x1), vs16(x2)));
+     b00 = ((vector float) vec_add(vs16(b70), vs16(b10)));
+     b40 = ((vector float) vec_sub(vs16(b70), vs16(b10)));
+ #define CTF0(n)                                                    \
+     b ## n ## 1 = ((vector float) vec_unpackl(vs16(b ## n ## 0))); \
+     b ## n ## 0 = ((vector float) vec_unpackh(vs16(b ## n ## 0))); \
+     b ## n ## 1 = vec_ctf(vs32(b ## n ## 1), 0);                   \
+     b ## n ## 0 = vec_ctf(vs32(b ## n ## 0), 0)
+     CTF0(0);
+     CTF0(4);
+     b20 = ((vector float) vec_sub(vs16(x0), vs16(x3)));
+     b60 = ((vector float) vec_sub(vs16(x1), vs16(x2)));
+     CTF0(2);
+     CTF0(6);
+ #undef CTF0
+     x0 = vec_add(b60, b20);
+     x1 = vec_add(b61, b21);
+     cnst = LD_W2;
+     x0   = vec_madd(cnst, x0, mzero);
+     x1   = vec_madd(cnst, x1, mzero);
+     cnst = LD_W1;
+     b20  = vec_madd(cnst, b20, x0);
+     b21  = vec_madd(cnst, b21, x1);
+     cnst = LD_W0;
+     b60  = vec_madd(cnst, b60, x0);
+     b61  = vec_madd(cnst, b61, x1);
+ #define CTFX(x, b)                                  \
+     b ## 0 = ((vector float) vec_unpackh(vs16(x))); \
+     b ## 1 = ((vector float) vec_unpackl(vs16(x))); \
+     b ## 0 = vec_ctf(vs32(b ## 0), 0);              \
+     b ## 1 = vec_ctf(vs32(b ## 1), 0)
+     CTFX(x4, b7);
+     CTFX(x5, b5);
+     CTFX(x6, b3);
+     CTFX(x7, b1);
+ #undef CTFX
+     x0   = vec_add(b70, b10);
+     x1   = vec_add(b50, b30);
+     x2   = vec_add(b70, b30);
+     x3   = vec_add(b50, b10);
+     x8   = vec_add(x2, x3);
+     cnst = LD_W3;
+     x8   = vec_madd(cnst, x8, mzero);
+     cnst = LD_W8;
+     x0   = vec_madd(cnst, x0, mzero);
+     cnst = LD_W9;
+     x1   = vec_madd(cnst, x1, mzero);
+     cnst = LD_WA;
+     x2   = vec_madd(cnst, x2, x8);
+     cnst = LD_WB;
+     x3   = vec_madd(cnst, x3, x8);
+     cnst = LD_W4;
+     b70  = vec_madd(cnst, b70, x0);
+     cnst = LD_W5;
+     b50  = vec_madd(cnst, b50, x1);
+     cnst = LD_W6;
+     b30  = vec_madd(cnst, b30, x1);
+     cnst = LD_W7;
+     b10  = vec_madd(cnst, b10, x0);
+     b70 = vec_add(b70, x2);
+     b50 = vec_add(b50, x3);
+     b30 = vec_add(b30, x2);
+     b10 = vec_add(b10, x3);
+     x0   = vec_add(b71, b11);
+     x1   = vec_add(b51, b31);
+     x2   = vec_add(b71, b31);
+     x3   = vec_add(b51, b11);
+     x8   = vec_add(x2, x3);
+     cnst = LD_W3;
+     x8   = vec_madd(cnst, x8, mzero);
+     cnst = LD_W8;
+     x0   = vec_madd(cnst, x0, mzero);
+     cnst = LD_W9;
+     x1   = vec_madd(cnst, x1, mzero);
+     cnst = LD_WA;
+     x2   = vec_madd(cnst, x2, x8);
+     cnst = LD_WB;
+     x3   = vec_madd(cnst, x3, x8);
+     cnst = LD_W4;
+     b71  = vec_madd(cnst, b71, x0);
+     cnst = LD_W5;
+     b51  = vec_madd(cnst, b51, x1);
+     cnst = LD_W6;
+     b31  = vec_madd(cnst, b31, x1);
+     cnst = LD_W7;
+     b11  = vec_madd(cnst, b11, x0);
+     b71 = vec_add(b71, x2);
+     b51 = vec_add(b51, x3);
+     b31 = vec_add(b31, x2);
+     b11 = vec_add(b11, x3);
+     /* }}} */
+     /* 8x8 matrix transpose (vector float[8][2]) {{{ */
+     x0 = vec_mergel(b00, b20);
+     x1 = vec_mergeh(b00, b20);
+     x2 = vec_mergel(b10, b30);
+     x3 = vec_mergeh(b10, b30);
+     b00 = vec_mergeh(x1, x3);
+     b10 = vec_mergel(x1, x3);
+     b20 = vec_mergeh(x0, x2);
+     b30 = vec_mergel(x0, x2);
+     x4 = vec_mergel(b41, b61);
+     x5 = vec_mergeh(b41, b61);
+     x6 = vec_mergel(b51, b71);
+     x7 = vec_mergeh(b51, b71);
+     b41 = vec_mergeh(x5, x7);
+     b51 = vec_mergel(x5, x7);
+     b61 = vec_mergeh(x4, x6);
+     b71 = vec_mergel(x4, x6);
+     x0 = vec_mergel(b01, b21);
+     x1 = vec_mergeh(b01, b21);
+     x2 = vec_mergel(b11, b31);
+     x3 = vec_mergeh(b11, b31);
+     x4 = vec_mergel(b40, b60);
+     x5 = vec_mergeh(b40, b60);
+     x6 = vec_mergel(b50, b70);
+     x7 = vec_mergeh(b50, b70);
+     b40 = vec_mergeh(x1, x3);
+     b50 = vec_mergel(x1, x3);
+     b60 = vec_mergeh(x0, x2);
+     b70 = vec_mergel(x0, x2);
+     b01 = vec_mergeh(x5, x7);
+     b11 = vec_mergel(x5, x7);
+     b21 = vec_mergeh(x4, x6);
+     b31 = vec_mergel(x4, x6);
+     /* }}} */
+     FDCTCOL(b00, b10, b20, b30, b40, b50, b60, b70);
+     FDCTCOL(b01, b11, b21, b31, b41, b51, b61, b71);
+     /* round, convert back to short {{{ */
+ #define CTS(n)                                                  \
+     b ## n ## 0 = vec_round(b ## n ## 0);                       \
+     b ## n ## 1 = vec_round(b ## n ## 1);                       \
+     b ## n ## 0 = ((vector float) vec_cts(b ## n ## 0, 0));     \
+     b ## n ## 1 = ((vector float) vec_cts(b ## n ## 1, 0));     \
+     b ## n ## 0 = ((vector float) vec_pack(vs32(b ## n ## 0),   \
+                                            vs32(b ## n ## 1))); \
+     vec_st(vs16(b ## n ## 0), 0, bp)
+     bp = (vector signed short *) block;
+     CTS(0);
+     bp++;
+     CTS(1);
+     bp++;
+     CTS(2);
+     bp++;
+     CTS(3);
+     bp++;
+     CTS(4);
+     bp++;
+     CTS(5);
+     bp++;
+     CTS(6);
+     bp++;
+     CTS(7);
+ #undef CTS
+     /* }}} */
+ }
+ #endif /* HAVE_ALTIVEC */
+ av_cold void ff_fdctdsp_init_ppc(FDCTDSPContext *c, AVCodecContext *avctx,
+                                  unsigned high_bit_depth)
+ {
+ #if HAVE_ALTIVEC
+     if (!PPC_ALTIVEC(av_get_cpu_flags()))
+         return;
+     if (!high_bit_depth) {
+         if (avctx->dct_algo == FF_DCT_AUTO ||
+             avctx->dct_algo == FF_DCT_ALTIVEC) {
+             c->fdct = ff_fdct_altivec;
+         }
+     }
+ #endif /* HAVE_ALTIVEC */
+ }
index 0000000,845b4fe..89be768
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,26 +1,26 @@@
 - * This file is part of Libav.
+ /*
 - * Libav is free software; you can redistribute it and/or
++ * This file is part of FFmpeg.
+  *
 - * Libav is distributed in the hope that it will be useful,
++ * FFmpeg is free software; you can redistribute it and/or
+  * modify it under the terms of the GNU Lesser General Public
+  * License as published by the Free Software Foundation; either
+  * version 2.1 of the License, or (at your option) any later version.
+  *
 - * License along with Libav; if not, write to the Free Software
++ * FFmpeg is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  * Lesser General Public License for more details.
+  *
+  * You should have received a copy of the GNU Lesser General Public
++ * License along with FFmpeg; if not, write to the Free Software
+  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+  */
+ #ifndef AVCODEC_PPC_FDCTDSP_H
+ #define AVCODEC_PPC_FDCTDSP_H
+ #include <stdint.h>
+ void ff_fdct_altivec(int16_t *block);
+ #endif /* AVCODEC_PPC_FDCTDSP_H */
index 23323bb,0000000..434021d
mode 100644,000000..100644
--- /dev/null
@@@ -1,630 -1,0 +1,631 @@@
-     DSPContext dsp;
 +/*
 + * Apple ProRes encoder
 + *
 + * Copyright (c) 2011 Anatoliy Wasserman
 + *
 + * This file is part of FFmpeg.
 + *
 + * FFmpeg is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU Lesser General Public
 + * License as published by the Free Software Foundation; either
 + * version 2.1 of the License, or (at your option) any later version.
 + *
 + * FFmpeg is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * Lesser General Public License for more details.
 + *
 + * You should have received a copy of the GNU Lesser General Public
 + * License along with FFmpeg; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
 +/**
 + * @file
 + * Apple ProRes encoder (Anatoliy Wasserman version)
 + * Known FOURCCs: 'apch' (HQ), 'apcn' (SD), 'apcs' (LT), 'acpo' (Proxy)
 + */
 +
 +#include "avcodec.h"
 +#include "dct.h"
 +#include "internal.h"
 +#include "put_bits.h"
 +#include "bytestream.h"
 +#include "dsputil.h"
++#include "fdctdsp.h"
 +
 +#define DEFAULT_SLICE_MB_WIDTH 8
 +
 +#define FF_PROFILE_PRORES_PROXY     0
 +#define FF_PROFILE_PRORES_LT        1
 +#define FF_PROFILE_PRORES_STANDARD  2
 +#define FF_PROFILE_PRORES_HQ        3
 +
 +static const AVProfile profiles[] = {
 +    { FF_PROFILE_PRORES_PROXY,    "apco"},
 +    { FF_PROFILE_PRORES_LT,       "apcs"},
 +    { FF_PROFILE_PRORES_STANDARD, "apcn"},
 +    { FF_PROFILE_PRORES_HQ,       "apch"},
 +    { FF_PROFILE_UNKNOWN }
 +};
 +
 +static const int qp_start_table[4] = { 4, 1, 1, 1 };
 +static const int qp_end_table[4]   = { 8, 9, 6, 6 };
 +static const int bitrate_table[5]  = { 1000, 2100, 3500, 5400 };
 +
 +static const uint8_t progressive_scan[64] = {
 +     0,  1,  8,  9,  2,  3, 10, 11,
 +    16, 17, 24, 25, 18, 19, 26, 27,
 +     4,  5, 12, 20, 13,  6,  7, 14,
 +    21, 28, 29, 22, 15, 23, 30, 31,
 +    32, 33, 40, 48, 41, 34, 35, 42,
 +    49, 56, 57, 50, 43, 36, 37, 44,
 +    51, 58, 59, 52, 45, 38, 39, 46,
 +    53, 60, 61, 54, 47, 55, 62, 63
 +};
 +
 +static const uint8_t QMAT_LUMA[4][64] = {
 +    {
 +         4,  7,  9, 11, 13, 14, 15, 63,
 +         7,  7, 11, 12, 14, 15, 63, 63,
 +         9, 11, 13, 14, 15, 63, 63, 63,
 +        11, 11, 13, 14, 63, 63, 63, 63,
 +        11, 13, 14, 63, 63, 63, 63, 63,
 +        13, 14, 63, 63, 63, 63, 63, 63,
 +        13, 63, 63, 63, 63, 63, 63, 63,
 +        63, 63, 63, 63, 63, 63, 63, 63
 +    }, {
 +         4,  5,  6,  7,  9, 11, 13, 15,
 +         5,  5,  7,  8, 11, 13, 15, 17,
 +         6,  7,  9, 11, 13, 15, 15, 17,
 +         7,  7,  9, 11, 13, 15, 17, 19,
 +         7,  9, 11, 13, 14, 16, 19, 23,
 +         9, 11, 13, 14, 16, 19, 23, 29,
 +         9, 11, 13, 15, 17, 21, 28, 35,
 +        11, 13, 16, 17, 21, 28, 35, 41
 +    }, {
 +         4,  4,  5,  5,  6,  7,  7,  9,
 +         4,  4,  5,  6,  7,  7,  9,  9,
 +         5,  5,  6,  7,  7,  9,  9, 10,
 +         5,  5,  6,  7,  7,  9,  9, 10,
 +         5,  6,  7,  7,  8,  9, 10, 12,
 +         6,  7,  7,  8,  9, 10, 12, 15,
 +         6,  7,  7,  9, 10, 11, 14, 17,
 +         7,  7,  9, 10, 11, 14, 17, 21
 +    }, {
 +         4,  4,  4,  4,  4,  4,  4,  4,
 +         4,  4,  4,  4,  4,  4,  4,  4,
 +         4,  4,  4,  4,  4,  4,  4,  4,
 +         4,  4,  4,  4,  4,  4,  4,  5,
 +         4,  4,  4,  4,  4,  4,  5,  5,
 +         4,  4,  4,  4,  4,  5,  5,  6,
 +         4,  4,  4,  4,  5,  5,  6,  7,
 +         4,  4,  4,  4,  5,  6,  7,  7
 +    }
 +};
 +
 +static const uint8_t QMAT_CHROMA[4][64] = {
 +    {
 +         4,  7,  9, 11, 13, 14, 63, 63,
 +         7,  7, 11, 12, 14, 63, 63, 63,
 +         9, 11, 13, 14, 63, 63, 63, 63,
 +        11, 11, 13, 14, 63, 63, 63, 63,
 +        11, 13, 14, 63, 63, 63, 63, 63,
 +        13, 14, 63, 63, 63, 63, 63, 63,
 +        13, 63, 63, 63, 63, 63, 63, 63,
 +        63, 63, 63, 63, 63, 63, 63, 63
 +    }, {
 +         4,  5,  6,  7,  9, 11, 13, 15,
 +         5,  5,  7,  8, 11, 13, 15, 17,
 +         6,  7,  9, 11, 13, 15, 15, 17,
 +         7,  7,  9, 11, 13, 15, 17, 19,
 +         7,  9, 11, 13, 14, 16, 19, 23,
 +         9, 11, 13, 14, 16, 19, 23, 29,
 +         9, 11, 13, 15, 17, 21, 28, 35,
 +        11, 13, 16, 17, 21, 28, 35, 41
 +    }, {
 +         4,  4,  5,  5,  6,  7,  7,  9,
 +         4,  4,  5,  6,  7,  7,  9,  9,
 +         5,  5,  6,  7,  7,  9,  9, 10,
 +         5,  5,  6,  7,  7,  9,  9, 10,
 +         5,  6,  7,  7,  8,  9, 10, 12,
 +         6,  7,  7,  8,  9, 10, 12, 15,
 +         6,  7,  7,  9, 10, 11, 14, 17,
 +         7,  7,  9, 10, 11, 14, 17, 21
 +    }, {
 +         4,  4,  4,  4,  4,  4,  4,  4,
 +         4,  4,  4,  4,  4,  4,  4,  4,
 +         4,  4,  4,  4,  4,  4,  4,  4,
 +         4,  4,  4,  4,  4,  4,  4,  5,
 +         4,  4,  4,  4,  4,  4,  5,  5,
 +         4,  4,  4,  4,  4,  5,  5,  6,
 +         4,  4,  4,  4,  5,  5,  6,  7,
 +         4,  4,  4,  4,  5,  6,  7,  7
 +    }
 +};
 +
 +
 +typedef struct {
- static void fdct_get(DSPContext *dsp, uint8_t *pixels, int stride, int16_t* block)
++    FDCTDSPContext fdsp;
 +    uint8_t* fill_y;
 +    uint8_t* fill_u;
 +    uint8_t* fill_v;
 +
 +    int qmat_luma[16][64];
 +    int qmat_chroma[16][64];
 +} ProresContext;
 +
 +static void encode_codeword(PutBitContext *pb, int val, int codebook)
 +{
 +    unsigned int rice_order, exp_order, switch_bits, first_exp, exp, zeros,
 +            mask;
 +
 +    /* number of bits to switch between rice and exp golomb */
 +    switch_bits = codebook & 3;
 +    rice_order  = codebook >> 5;
 +    exp_order   = (codebook >> 2) & 7;
 +
 +    first_exp = ((switch_bits + 1) << rice_order);
 +
 +    if (val >= first_exp) { /* exp golomb */
 +        val -= first_exp;
 +        val += (1 << exp_order);
 +        exp = av_log2(val);
 +        zeros = exp - exp_order + switch_bits + 1;
 +        put_bits(pb, zeros, 0);
 +        put_bits(pb, exp + 1, val);
 +    } else if (rice_order) {
 +        mask = (1 << rice_order) - 1;
 +        put_bits(pb, (val >> rice_order), 0);
 +        put_bits(pb, 1, 1);
 +        put_bits(pb, rice_order, val & mask);
 +    } else {
 +        put_bits(pb, val, 0);
 +        put_bits(pb, 1, 1);
 +    }
 +}
 +
 +#define QSCALE(qmat,ind,val) ((val) / ((qmat)[ind]))
 +#define TO_GOLOMB(val) (((val) << 1) ^ ((val) >> 31))
 +#define DIFF_SIGN(val, sign) (((val) >> 31) ^ (sign))
 +#define IS_NEGATIVE(val) ((((val) >> 31) ^ -1) + 1)
 +#define TO_GOLOMB2(val,sign) ((val)==0 ? 0 : ((val) << 1) + (sign))
 +
 +static av_always_inline int get_level(int val)
 +{
 +    int sign = (val >> 31);
 +    return (val ^ sign) - sign;
 +}
 +
 +#define FIRST_DC_CB 0xB8
 +
 +static const uint8_t dc_codebook[7] = { 0x04, 0x28, 0x28, 0x4D, 0x4D, 0x70, 0x70};
 +
 +static void encode_dc_coeffs(PutBitContext *pb, int16_t *in,
 +        int blocks_per_slice, int *qmat)
 +{
 +    int prev_dc, code;
 +    int i, sign, idx;
 +    int new_dc, delta, diff_sign, new_code;
 +
 +    prev_dc = QSCALE(qmat, 0, in[0] - 16384);
 +    code = TO_GOLOMB(prev_dc);
 +    encode_codeword(pb, code, FIRST_DC_CB);
 +
 +    code = 5; sign = 0; idx = 64;
 +    for (i = 1; i < blocks_per_slice; i++, idx += 64) {
 +        new_dc    = QSCALE(qmat, 0, in[idx] - 16384);
 +        delta     = new_dc - prev_dc;
 +        diff_sign = DIFF_SIGN(delta, sign);
 +        new_code  = TO_GOLOMB2(get_level(delta), diff_sign);
 +
 +        encode_codeword(pb, new_code, dc_codebook[FFMIN(code, 6)]);
 +
 +        code      = new_code;
 +        sign      = delta >> 31;
 +        prev_dc   = new_dc;
 +    }
 +}
 +
 +static const uint8_t run_to_cb[16] = { 0x06, 0x06, 0x05, 0x05, 0x04, 0x29,
 +        0x29, 0x29, 0x29, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x4C };
 +static const uint8_t lev_to_cb[10] = { 0x04, 0x0A, 0x05, 0x06, 0x04, 0x28,
 +        0x28, 0x28, 0x28, 0x4C };
 +
 +static void encode_ac_coeffs(AVCodecContext *avctx, PutBitContext *pb,
 +        int16_t *in, int blocks_per_slice, int *qmat)
 +{
 +    int prev_run = 4;
 +    int prev_level = 2;
 +
 +    int run = 0, level, code, i, j;
 +    for (i = 1; i < 64; i++) {
 +        int indp = progressive_scan[i];
 +        for (j = 0; j < blocks_per_slice; j++) {
 +            int val = QSCALE(qmat, indp, in[(j << 6) + indp]);
 +            if (val) {
 +                encode_codeword(pb, run, run_to_cb[FFMIN(prev_run, 15)]);
 +
 +                prev_run   = run;
 +                run        = 0;
 +                level      = get_level(val);
 +                code       = level - 1;
 +
 +                encode_codeword(pb, code, lev_to_cb[FFMIN(prev_level, 9)]);
 +
 +                prev_level = level;
 +
 +                put_bits(pb, 1, IS_NEGATIVE(val));
 +            } else {
 +                ++run;
 +            }
 +        }
 +    }
 +}
 +
 +static void get(uint8_t *pixels, int stride, int16_t* block)
 +{
 +    int i;
 +
 +    for (i = 0; i < 8; i++) {
 +        AV_WN64(block, AV_RN64(pixels));
 +        AV_WN64(block+4, AV_RN64(pixels+8));
 +        pixels += stride;
 +        block += 8;
 +    }
 +}
 +
-     dsp->fdct(block);
++static void fdct_get(FDCTDSPContext *fdsp, uint8_t *pixels, int stride, int16_t* block)
 +{
 +    get(pixels, stride, block);
-     DSPContext *dsp = &ctx->dsp;
++    fdsp->fdct(block);
 +}
 +
 +static int encode_slice_plane(AVCodecContext *avctx, int mb_count,
 +        uint8_t *src, int src_stride, uint8_t *buf, unsigned buf_size,
 +        int *qmat, int chroma)
 +{
 +    ProresContext* ctx = avctx->priv_data;
-         fdct_get(dsp, src,                  src_stride, block + (0 << 6));
-         fdct_get(dsp, src + 8 * src_stride, src_stride, block + ((2 - chroma) << 6));
++    FDCTDSPContext *fdsp = &ctx->fdsp;
 +    DECLARE_ALIGNED(16, int16_t, blocks)[DEFAULT_SLICE_MB_WIDTH << 8], *block;
 +    int i, blocks_per_slice;
 +    PutBitContext pb;
 +
 +    block = blocks;
 +    for (i = 0; i < mb_count; i++) {
-             fdct_get(dsp, src + 16,                  src_stride, block + (1 << 6));
-             fdct_get(dsp, src + 16 + 8 * src_stride, src_stride, block + (3 << 6));
++        fdct_get(fdsp, src,                  src_stride, block + (0 << 6));
++        fdct_get(fdsp, src + 8 * src_stride, src_stride, block + ((2 - chroma) << 6));
 +        if (!chroma) {
-     ff_dsputil_init(&ctx->dsp, avctx);
++            fdct_get(fdsp, src + 16,                  src_stride, block + (1 << 6));
++            fdct_get(fdsp, src + 16 + 8 * src_stride, src_stride, block + (3 << 6));
 +        }
 +
 +        block += (256 >> chroma);
 +        src   += (32  >> chroma);
 +    }
 +
 +    blocks_per_slice = mb_count << (2 - chroma);
 +    init_put_bits(&pb, buf, buf_size << 3);
 +
 +    encode_dc_coeffs(&pb, blocks, blocks_per_slice, qmat);
 +    encode_ac_coeffs(avctx, &pb, blocks, blocks_per_slice, qmat);
 +
 +    flush_put_bits(&pb);
 +    return put_bits_ptr(&pb) - pb.buf;
 +}
 +
 +static av_always_inline unsigned encode_slice_data(AVCodecContext *avctx,
 +        uint8_t *dest_y, uint8_t *dest_u, uint8_t *dest_v, int luma_stride,
 +        int chroma_stride, unsigned mb_count, uint8_t *buf, unsigned data_size,
 +        unsigned* y_data_size, unsigned* u_data_size, unsigned* v_data_size,
 +        int qp)
 +{
 +    ProresContext* ctx = avctx->priv_data;
 +
 +    *y_data_size = encode_slice_plane(avctx, mb_count, dest_y, luma_stride,
 +            buf, data_size, ctx->qmat_luma[qp - 1], 0);
 +
 +    if (!(avctx->flags & CODEC_FLAG_GRAY)) {
 +        *u_data_size = encode_slice_plane(avctx, mb_count, dest_u,
 +                chroma_stride, buf + *y_data_size, data_size - *y_data_size,
 +                ctx->qmat_chroma[qp - 1], 1);
 +
 +        *v_data_size = encode_slice_plane(avctx, mb_count, dest_v,
 +                chroma_stride, buf + *y_data_size + *u_data_size,
 +                data_size - *y_data_size - *u_data_size,
 +                ctx->qmat_chroma[qp - 1], 1);
 +    }
 +
 +    return *y_data_size + *u_data_size + *v_data_size;
 +}
 +
 +static void subimage_with_fill(uint16_t *src, unsigned x, unsigned y,
 +        unsigned stride, unsigned width, unsigned height, uint16_t *dst,
 +        unsigned dst_width, unsigned dst_height)
 +{
 +
 +    int box_width = FFMIN(width - x, dst_width);
 +    int box_height = FFMIN(height - y, dst_height);
 +    int i, j, src_stride = stride >> 1;
 +    uint16_t last_pix, *last_line;
 +
 +    src += y * src_stride + x;
 +    for (i = 0; i < box_height; ++i) {
 +        for (j = 0; j < box_width; ++j) {
 +            dst[j] = src[j];
 +        }
 +        last_pix = dst[j - 1];
 +        for (; j < dst_width; j++)
 +            dst[j] = last_pix;
 +        src += src_stride;
 +        dst += dst_width;
 +    }
 +    last_line = dst - dst_width;
 +    for (; i < dst_height; i++) {
 +        for (j = 0; j < dst_width; ++j) {
 +            dst[j] = last_line[j];
 +        }
 +        dst += dst_width;
 +    }
 +}
 +
 +static int encode_slice(AVCodecContext *avctx, const AVFrame *pic, int mb_x,
 +        int mb_y, unsigned mb_count, uint8_t *buf, unsigned data_size,
 +        int unsafe, int *qp)
 +{
 +    int luma_stride, chroma_stride;
 +    int hdr_size = 6, slice_size;
 +    uint8_t *dest_y, *dest_u, *dest_v;
 +    unsigned y_data_size = 0, u_data_size = 0, v_data_size = 0;
 +    ProresContext* ctx = avctx->priv_data;
 +    int tgt_bits   = (mb_count * bitrate_table[avctx->profile]) >> 2;
 +    int low_bytes  = (tgt_bits - (tgt_bits >> 3)) >> 3; // 12% bitrate fluctuation
 +    int high_bytes = (tgt_bits + (tgt_bits >> 3)) >> 3;
 +
 +    luma_stride   = pic->linesize[0];
 +    chroma_stride = pic->linesize[1];
 +
 +    dest_y = pic->data[0] + (mb_y << 4) * luma_stride   + (mb_x << 5);
 +    dest_u = pic->data[1] + (mb_y << 4) * chroma_stride + (mb_x << 4);
 +    dest_v = pic->data[2] + (mb_y << 4) * chroma_stride + (mb_x << 4);
 +
 +    if (unsafe) {
 +
 +        subimage_with_fill((uint16_t *) pic->data[0], mb_x << 4, mb_y << 4,
 +                luma_stride, avctx->width, avctx->height,
 +                (uint16_t *) ctx->fill_y, mb_count << 4, 16);
 +        subimage_with_fill((uint16_t *) pic->data[1], mb_x << 3, mb_y << 4,
 +                chroma_stride, avctx->width >> 1, avctx->height,
 +                (uint16_t *) ctx->fill_u, mb_count << 3, 16);
 +        subimage_with_fill((uint16_t *) pic->data[2], mb_x << 3, mb_y << 4,
 +                chroma_stride, avctx->width >> 1, avctx->height,
 +                (uint16_t *) ctx->fill_v, mb_count << 3, 16);
 +
 +        encode_slice_data(avctx, ctx->fill_y, ctx->fill_u, ctx->fill_v,
 +                mb_count << 5, mb_count << 4, mb_count, buf + hdr_size,
 +                data_size - hdr_size, &y_data_size, &u_data_size, &v_data_size,
 +                *qp);
 +    } else {
 +        slice_size = encode_slice_data(avctx, dest_y, dest_u, dest_v,
 +                luma_stride, chroma_stride, mb_count, buf + hdr_size,
 +                data_size - hdr_size, &y_data_size, &u_data_size, &v_data_size,
 +                *qp);
 +
 +        if (slice_size > high_bytes && *qp < qp_end_table[avctx->profile]) {
 +            do {
 +                *qp += 1;
 +                slice_size = encode_slice_data(avctx, dest_y, dest_u, dest_v,
 +                        luma_stride, chroma_stride, mb_count, buf + hdr_size,
 +                        data_size - hdr_size, &y_data_size, &u_data_size,
 +                        &v_data_size, *qp);
 +            } while (slice_size > high_bytes && *qp < qp_end_table[avctx->profile]);
 +        } else if (slice_size < low_bytes && *qp
 +                > qp_start_table[avctx->profile]) {
 +            do {
 +                *qp -= 1;
 +                slice_size = encode_slice_data(avctx, dest_y, dest_u, dest_v,
 +                        luma_stride, chroma_stride, mb_count, buf + hdr_size,
 +                        data_size - hdr_size, &y_data_size, &u_data_size,
 +                        &v_data_size, *qp);
 +            } while (slice_size < low_bytes && *qp > qp_start_table[avctx->profile]);
 +        }
 +    }
 +
 +    buf[0] = hdr_size << 3;
 +    buf[1] = *qp;
 +    AV_WB16(buf + 2, y_data_size);
 +    AV_WB16(buf + 4, u_data_size);
 +
 +    return hdr_size + y_data_size + u_data_size + v_data_size;
 +}
 +
 +static int prores_encode_picture(AVCodecContext *avctx, const AVFrame *pic,
 +        uint8_t *buf, const int buf_size)
 +{
 +    int mb_width = (avctx->width + 15) >> 4;
 +    int mb_height = (avctx->height + 15) >> 4;
 +    int hdr_size, sl_size, i;
 +    int mb_y, sl_data_size, qp;
 +    int unsafe_bot, unsafe_right;
 +    uint8_t *sl_data, *sl_data_sizes;
 +    int slice_per_line = 0, rem = mb_width;
 +
 +    for (i = av_log2(DEFAULT_SLICE_MB_WIDTH); i >= 0; --i) {
 +        slice_per_line += rem >> i;
 +        rem &= (1 << i) - 1;
 +    }
 +
 +    qp = qp_start_table[avctx->profile];
 +    hdr_size = 8; sl_data_size = buf_size - hdr_size;
 +    sl_data_sizes = buf + hdr_size;
 +    sl_data = sl_data_sizes + (slice_per_line * mb_height * 2);
 +    for (mb_y = 0; mb_y < mb_height; mb_y++) {
 +        int mb_x = 0;
 +        int slice_mb_count = DEFAULT_SLICE_MB_WIDTH;
 +        while (mb_x < mb_width) {
 +            while (mb_width - mb_x < slice_mb_count)
 +                slice_mb_count >>= 1;
 +
 +            unsafe_bot = (avctx->height & 0xf) && (mb_y == mb_height - 1);
 +            unsafe_right = (avctx->width & 0xf) && (mb_x + slice_mb_count == mb_width);
 +
 +            sl_size = encode_slice(avctx, pic, mb_x, mb_y, slice_mb_count,
 +                    sl_data, sl_data_size, unsafe_bot || unsafe_right, &qp);
 +
 +            bytestream_put_be16(&sl_data_sizes, sl_size);
 +            sl_data           += sl_size;
 +            sl_data_size      -= sl_size;
 +            mb_x              += slice_mb_count;
 +        }
 +    }
 +
 +    buf[0] = hdr_size << 3;
 +    AV_WB32(buf + 1, sl_data - buf);
 +    AV_WB16(buf + 5, slice_per_line * mb_height);
 +    buf[7] = av_log2(DEFAULT_SLICE_MB_WIDTH) << 4;
 +
 +    return sl_data - buf;
 +}
 +
 +static int prores_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
 +                               const AVFrame *pict, int *got_packet)
 +{
 +    int header_size = 148;
 +    uint8_t *buf;
 +    int pic_size, ret;
 +    int frame_size = FFALIGN(avctx->width, 16) * FFALIGN(avctx->height, 16)*16 + 500 + FF_MIN_BUFFER_SIZE; //FIXME choose tighter limit
 +
 +
 +    if ((ret = ff_alloc_packet2(avctx, pkt, frame_size + FF_MIN_BUFFER_SIZE)) < 0)
 +        return ret;
 +
 +    buf = pkt->data;
 +    pic_size = prores_encode_picture(avctx, pict, buf + header_size + 8,
 +            pkt->size - header_size - 8);
 +
 +    bytestream_put_be32(&buf, pic_size + 8 + header_size);
 +    bytestream_put_buffer(&buf, "icpf", 4);
 +
 +    bytestream_put_be16(&buf, header_size);
 +    bytestream_put_be16(&buf, 0);
 +    bytestream_put_buffer(&buf, "fmpg", 4);
 +    bytestream_put_be16(&buf, avctx->width);
 +    bytestream_put_be16(&buf, avctx->height);
 +    *buf++ = 0x83; // {10}(422){00}{00}(frame){11}
 +    *buf++ = 0;
 +    *buf++ = 2;
 +    *buf++ = 2;
 +    *buf++ = 6;
 +    *buf++ = 32;
 +    *buf++ = 0;
 +    *buf++ = 3;
 +
 +    bytestream_put_buffer(&buf, QMAT_LUMA[avctx->profile],   64);
 +    bytestream_put_buffer(&buf, QMAT_CHROMA[avctx->profile], 64);
 +
 +    pkt->flags |= AV_PKT_FLAG_KEY;
 +    pkt->size = pic_size + 8 + header_size;
 +    *got_packet = 1;
 +
 +    return 0;
 +}
 +
 +static void scale_mat(const uint8_t* src, int* dst, int scale)
 +{
 +    int i;
 +    for (i = 0; i < 64; i++)
 +        dst[i] = src[i] * scale;
 +}
 +
 +static av_cold int prores_encode_init(AVCodecContext *avctx)
 +{
 +    int i;
 +    ProresContext* ctx = avctx->priv_data;
 +
 +    if (avctx->pix_fmt != AV_PIX_FMT_YUV422P10) {
 +        av_log(avctx, AV_LOG_ERROR, "need YUV422P10\n");
 +        return -1;
 +    }
 +    avctx->bits_per_raw_sample = 10;
 +
 +    if (avctx->width & 0x1) {
 +        av_log(avctx, AV_LOG_ERROR,
 +                "frame width needs to be multiple of 2\n");
 +        return -1;
 +    }
 +
 +    if ((avctx->height & 0xf) || (avctx->width & 0xf)) {
 +        ctx->fill_y = av_malloc(4 * (DEFAULT_SLICE_MB_WIDTH << 8));
 +        if (!ctx->fill_y)
 +            return AVERROR(ENOMEM);
 +        ctx->fill_u = ctx->fill_y + (DEFAULT_SLICE_MB_WIDTH << 9);
 +        ctx->fill_v = ctx->fill_u + (DEFAULT_SLICE_MB_WIDTH << 8);
 +    }
 +
 +    if (avctx->profile == FF_PROFILE_UNKNOWN) {
 +        avctx->profile = FF_PROFILE_PRORES_STANDARD;
 +        av_log(avctx, AV_LOG_INFO,
 +                "encoding with ProRes standard (apcn) profile\n");
 +
 +    } else if (avctx->profile < FF_PROFILE_PRORES_PROXY
 +            || avctx->profile > FF_PROFILE_PRORES_HQ) {
 +        av_log(
 +                avctx,
 +                AV_LOG_ERROR,
 +                "unknown profile %d, use [0 - apco, 1 - apcs, 2 - apcn (default), 3 - apch]\n",
 +                avctx->profile);
 +        return -1;
 +    }
 +
++    ff_fdctdsp_init(&ctx->fdsp, avctx);
 +
 +    avctx->codec_tag = AV_RL32((const uint8_t*)profiles[avctx->profile].name);
 +
 +    for (i = 1; i <= 16; i++) {
 +        scale_mat(QMAT_LUMA[avctx->profile]  , ctx->qmat_luma[i - 1]  , i);
 +        scale_mat(QMAT_CHROMA[avctx->profile], ctx->qmat_chroma[i - 1], i);
 +    }
 +
 +    avctx->coded_frame = av_frame_alloc();
 +    avctx->coded_frame->key_frame = 1;
 +    avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I;
 +
 +    return 0;
 +}
 +
 +static av_cold int prores_encode_close(AVCodecContext *avctx)
 +{
 +    ProresContext* ctx = avctx->priv_data;
 +    av_freep(&avctx->coded_frame);
 +    av_freep(&ctx->fill_y);
 +
 +    return 0;
 +}
 +
 +AVCodec ff_prores_aw_encoder = {
 +    .name           = "prores_aw",
 +    .long_name      = NULL_IF_CONFIG_SMALL("Apple ProRes"),
 +    .type           = AVMEDIA_TYPE_VIDEO,
 +    .id             = AV_CODEC_ID_PRORES,
 +    .priv_data_size = sizeof(ProresContext),
 +    .init           = prores_encode_init,
 +    .close          = prores_encode_close,
 +    .encode2        = prores_encode_frame,
 +    .pix_fmts       = (const enum AVPixelFormat[]){AV_PIX_FMT_YUV422P10, AV_PIX_FMT_NONE},
 +    .capabilities   = CODEC_CAP_FRAME_THREADS | CODEC_CAP_INTRA_ONLY,
 +    .profiles       = profiles
 +};
 +
 +AVCodec ff_prores_encoder = {
 +    .name           = "prores",
 +    .long_name      = NULL_IF_CONFIG_SMALL("Apple ProRes"),
 +    .type           = AVMEDIA_TYPE_VIDEO,
 +    .id             = AV_CODEC_ID_PRORES,
 +    .priv_data_size = sizeof(ProresContext),
 +    .init           = prores_encode_init,
 +    .close          = prores_encode_close,
 +    .encode2        = prores_encode_frame,
 +    .pix_fmts       = (const enum AVPixelFormat[]){AV_PIX_FMT_YUV422P10, AV_PIX_FMT_NONE},
 +    .capabilities   = CODEC_CAP_FRAME_THREADS | CODEC_CAP_INTRA_ONLY,
 +    .profiles       = profiles
 +};
index ea1fd8a,0000000..93bcde7
mode 100644,000000..100644
--- /dev/null
@@@ -1,1292 -1,0 +1,1291 @@@
- #include "dct.h"
- #include "dsputil.h"
 +/*
 + * 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 FFmpeg.
 + *
 + * FFmpeg is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU Lesser General Public
 + * License as published by the Free Software Foundation; either
 + * version 2.1 of the License, or (at your option) any later version.
 + *
 + * FFmpeg is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * Lesser General Public License for more details.
 + *
 + * You should have received a copy of the GNU Lesser General Public
 + * License along with FFmpeg; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
 +#include "libavutil/opt.h"
 +#include "libavutil/pixdesc.h"
 +#include "avcodec.h"
-     void (* fdct)(DSPContext *dsp, const uint16_t *src,
-                   int linesize, int16_t *block);
-     DSPContext dsp;
++#include "fdctdsp.h"
 +#include "put_bits.h"
 +#include "bytestream.h"
 +#include "internal.h"
 +#include "proresdata.h"
 +
 +#define CFACTOR_Y422 2
 +#define CFACTOR_Y444 3
 +
 +#define MAX_MBS_PER_SLICE 8
 +
 +#define MAX_PLANES 4
 +
 +enum {
 +    PRORES_PROFILE_PROXY = 0,
 +    PRORES_PROFILE_LT,
 +    PRORES_PROFILE_STANDARD,
 +    PRORES_PROFILE_HQ,
 +    PRORES_PROFILE_4444,
 +};
 +
 +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[5] = {
 +    {
 +        .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,
 +    },
 +    {
 +        .full_name = "4444",
 +        .tag       = MKTAG('a', 'p', '4', 'h'),
 +        .min_quant = 1,
 +        .max_quant = 6,
 +        .br_tab    = { 2350, 1828, 1600, 1425 },
 +        .quant     = QUANT_MAT_HQ,
 +    }
 +};
 +
 +#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, 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;
 +    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;
 +    const uint8_t *scantable;
 +
-             ctx->fdct(&ctx->dsp, esrc, elinesize, blocks);
++    void (*fdct)(FDCTDSPContext *fdsp, const uint16_t *src,
++                 int linesize, int16_t *block);
++    FDCTDSPContext fdsp;
 +
 +    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;
 +    int alpha_bits;
 +
 +    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,
 +                           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->fdct(&ctx->dsp, esrc + 8, elinesize, blocks);
++            ctx->fdct(&ctx->fdsp, esrc, elinesize, blocks);
 +            blocks += 64;
 +            if (blocks_per_mb > 2) {
-             ctx->fdct(&ctx->dsp, esrc + elinesize * 4, elinesize, blocks);
++                ctx->fdct(&ctx->fdsp, esrc + 8, elinesize, blocks);
 +                blocks += 64;
 +            }
-                 ctx->fdct(&ctx->dsp, esrc + elinesize * 4 + 8, elinesize, blocks);
++            ctx->fdct(&ctx->fdsp, esrc + elinesize * 4, elinesize, blocks);
 +            blocks += 64;
 +            if (blocks_per_mb > 2) {
-             ctx->fdct(&ctx->dsp, esrc, elinesize, blocks);
++                ctx->fdct(&ctx->fdsp, esrc + elinesize * 4 + 8, elinesize, blocks);
 +                blocks += 64;
 +            }
 +        } else {
-             ctx->fdct(&ctx->dsp, esrc + elinesize * 4, elinesize, blocks);
++            ctx->fdct(&ctx->fdsp, esrc, elinesize, blocks);
 +            blocks += 64;
-                 ctx->fdct(&ctx->dsp, esrc + 8, elinesize, blocks);
++            ctx->fdct(&ctx->fdsp, esrc + elinesize * 4, elinesize, blocks);
 +            blocks += 64;
 +            if (blocks_per_mb > 2) {
-                 ctx->fdct(&ctx->dsp, esrc + elinesize * 4 + 8, elinesize, blocks);
++                ctx->fdct(&ctx->fdsp, esrc + 8, elinesize, blocks);
 +                blocks += 64;
- static void prores_fdct(DSPContext *dsp, const uint16_t *src,
++                ctx->fdct(&ctx->fdsp, esrc + elinesize * 4 + 8, elinesize, blocks);
 +                blocks += 64;
 +            }
 +        }
 +
 +        x += mb_width;
 +    }
 +}
 +
 +static void get_alpha_data(ProresContext *ctx, const uint16_t *src,
 +                           int linesize, int x, int y, int w, int h,
 +                           int16_t *blocks, int mbs_per_slice, int abits)
 +{
 +    const int slice_width = 16 * mbs_per_slice;
 +    int i, j, copy_w, copy_h;
 +
 +    copy_w = FFMIN(w - x, slice_width);
 +    copy_h = FFMIN(h - y, 16);
 +    for (i = 0; i < copy_h; i++) {
 +        memcpy(blocks, src, copy_w * sizeof(*src));
 +        if (abits == 8)
 +            for (j = 0; j < copy_w; j++)
 +                blocks[j] >>= 2;
 +        else
 +            for (j = 0; j < copy_w; j++)
 +                blocks[j] = (blocks[j] << 6) | (blocks[j] >> 4);
 +        for (j = copy_w; j < slice_width; j++)
 +            blocks[j] = blocks[copy_w - 1];
 +        blocks += slice_width;
 +        src    += linesize >> 1;
 +    }
 +    for (; i < 16; i++) {
 +        memcpy(blocks, blocks - slice_width, slice_width * sizeof(*blocks));
 +        blocks += slice_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_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;
 +    }
 +}
 +
 +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,
 +                              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, qmat);
 +    flush_put_bits(pb);
 +
 +    return (put_bits_count(pb) - saved_pos) >> 3;
 +}
 +
 +static void put_alpha_diff(PutBitContext *pb, int cur, int prev, int abits)
 +{
 +    const int mask  = (1 << abits) - 1;
 +    const int dbits = (abits == 8) ? 4 : 7;
 +    const int dsize = 1 << dbits - 1;
 +    int diff = cur - prev;
 +
 +    diff &= mask;
 +    if (diff >= (1 << abits) - dsize)
 +        diff -= 1 << abits;
 +    if (diff < -dsize || diff > dsize || !diff) {
 +        put_bits(pb, 1, 1);
 +        put_bits(pb, abits, diff);
 +    } else {
 +        put_bits(pb, 1, 0);
 +        put_bits(pb, dbits - 1, FFABS(diff) - 1);
 +        put_bits(pb, 1, diff < 0);
 +    }
 +}
 +
 +static void put_alpha_run(PutBitContext *pb, int run)
 +{
 +    if (run) {
 +        put_bits(pb, 1, 0);
 +        if (run < 0x10)
 +            put_bits(pb, 4, run);
 +        else
 +            put_bits(pb, 15, run);
 +    } else {
 +        put_bits(pb, 1, 1);
 +    }
 +}
 +
 +// todo alpha quantisation for high quants
 +static int encode_alpha_plane(ProresContext *ctx, PutBitContext *pb,
 +                              const uint16_t *src, int linesize,
 +                              int mbs_per_slice, uint16_t *blocks,
 +                              int quant)
 +{
 +    const int abits = ctx->alpha_bits;
 +    const int mask  = (1 << abits) - 1;
 +    const int num_coeffs = mbs_per_slice * 256;
 +    int saved_pos = put_bits_count(pb);
 +    int prev = mask, cur;
 +    int idx = 0;
 +    int run = 0;
 +
 +    cur = blocks[idx++];
 +    put_alpha_diff(pb, cur, prev, abits);
 +    prev = cur;
 +    do {
 +        cur = blocks[idx++];
 +        if (cur != prev) {
 +            put_alpha_run (pb, run);
 +            put_alpha_diff(pb, cur, prev, abits);
 +            prev = cur;
 +            run  = 0;
 +        } else {
 +            run++;
 +        }
 +    } while (idx < num_coeffs);
 +    if (run)
 +        put_alpha_run(pb, run);
 +    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;
 +
 +        if (i < 3) {
 +            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);
 +        } else {
 +            get_alpha_data(ctx, src, linesize, xp, yp,
 +                           pwidth, avctx->height / ctx->pictures_per_frame,
 +                           ctx->blocks[0], mbs_per_slice, ctx->alpha_bits);
 +            sizes[i] = encode_alpha_plane(ctx, pb, src, linesize,
 +                                          mbs_per_slice, ctx->blocks[0],
 +                                          quant);
 +        }
 +        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_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, qmat);
 +
 +    return FFALIGN(bits, 8);
 +}
 +
 +static int est_alpha_diff(int cur, int prev, int abits)
 +{
 +    const int mask  = (1 << abits) - 1;
 +    const int dbits = (abits == 8) ? 4 : 7;
 +    const int dsize = 1 << dbits - 1;
 +    int diff = cur - prev;
 +
 +    diff &= mask;
 +    if (diff >= (1 << abits) - dsize)
 +        diff -= 1 << abits;
 +    if (diff < -dsize || diff > dsize || !diff)
 +        return abits + 1;
 +    else
 +        return dbits + 1;
 +}
 +
 +static int estimate_alpha_plane(ProresContext *ctx, int *error,
 +                                const uint16_t *src, int linesize,
 +                                int mbs_per_slice, int quant,
 +                                int16_t *blocks)
 +{
 +    const int abits = ctx->alpha_bits;
 +    const int mask  = (1 << abits) - 1;
 +    const int num_coeffs = mbs_per_slice * 256;
 +    int prev = mask, cur;
 +    int idx = 0;
 +    int run = 0;
 +    int bits;
 +
 +    *error = 0;
 +    cur = blocks[idx++];
 +    bits = est_alpha_diff(cur, prev, abits);
 +    prev = cur;
 +    do {
 +        cur = blocks[idx++];
 +        if (cur != prev) {
 +            if (!run)
 +                bits++;
 +            else if (run < 0x10)
 +                bits += 4;
 +            else
 +                bits += 15;
 +            bits += est_alpha_diff(cur, prev, abits);
 +            prev = cur;
 +            run  = 0;
 +        } else {
 +            run++;
 +        }
 +    } while (idx < num_coeffs);
 +
 +    if (run) {
 +        if (run < 0x10)
 +            bits += 4;
 +        else
 +            bits += 15;
 +    }
 +
 +    return bits;
 +}
 +
 +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;
 +
 +        if (i < 3) {
 +            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]);
 +        } else {
 +            get_alpha_data(ctx, src, linesize[i], xp, yp,
 +                           pwidth, avctx->height / ctx->pictures_per_frame,
 +                           td->blocks[i], mbs_per_slice, ctx->alpha_bits);
 +        }
 +    }
 +
 +    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 - !!ctx->alpha_bits; 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 (ctx->alpha_bits)
 +            bits += estimate_alpha_plane(ctx, &error, src, linesize[3],
 +                                         mbs_per_slice, q, td->blocks[3]);
 +        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 - !!ctx->alpha_bits; i++) {
 +                bits += estimate_slice_plane(ctx, &error, i,
 +                                             src, linesize[i],
 +                                             mbs_per_slice,
 +                                             num_cblocks[i], plane_factor[i],
 +                                             qmat, td);
 +            }
 +            if (ctx->alpha_bits)
 +                bits += estimate_alpha_plane(ctx, &error, src, linesize[3],
 +                                             mbs_per_slice, q, td->blocks[3]);
 +            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 | (ctx->alpha_bits >> 3));
 +    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;
 +}
 +
-     dsp->fdct(block);
++static void prores_fdct(FDCTDSPContext *fdsp, const uint16_t *src,
 +                        int linesize, int16_t *block)
 +{
 +    int x, y;
 +    const uint16_t *tsrc = src;
 +
 +    for (y = 0; y < 8; y++) {
 +        for (x = 0; x < 8; x++)
 +            block[y * 8 + x] = tsrc[x];
 +        tsrc += linesize >> 1;
 +    }
-     ff_dsputil_init(&ctx->dsp, avctx);
++    fdsp->fdct(block);
 +}
 +
 +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 = av_frame_alloc();
 +    if (!avctx->coded_frame)
 +        return AVERROR(ENOMEM);
 +
 +    ctx->fdct      = prores_fdct;
 +    ctx->scantable = interlaced ? ff_prores_interlaced_scan
 +                                : ff_prores_progressive_scan;
++    ff_fdctdsp_init(&ctx->fdsp, avctx);
 +
 +    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);
 +    }
 +    if (av_pix_fmt_desc_get(avctx->pix_fmt)->flags & AV_PIX_FMT_FLAG_ALPHA) {
 +        if (ctx->alpha_bits & 7) {
 +            av_log(avctx, AV_LOG_ERROR, "alpha bits should be 0, 8 or 16\n");
 +            return AVERROR(EINVAL);
 +        }
 +    } else {
 +        ctx->alpha_bits = 0;
 +    }
 +
 +    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->alpha_bits;
 +
 +    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_4444, 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" },
 +    { "4444",          NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PRORES_PROFILE_4444 },
 +        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" },
 +    { "alpha_bits", "bits for alpha plane", OFFSET(alpha_bits), AV_OPT_TYPE_INT,
 +        { .i64 = 16 }, 0, 16, VE },
 +    { 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_ks_encoder = {
 +    .name           = "prores_ks",
 +    .long_name      = NULL_IF_CONFIG_SMALL("Apple ProRes (iCodec Pro)"),
 +    .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,
 +    .pix_fmts       = (const enum AVPixelFormat[]) {
 +                          AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10,
 +                          AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_NONE
 +                      },
 +    .priv_class     = &proresenc_class,
 +};
@@@ -9,9 -9,8 +9,10 @@@ OBJS-$(CONFIG_DCT)                     
  OBJS-$(CONFIG_DSPUTIL)                 += x86/dsputil_init.o
  OBJS-$(CONFIG_ENCODERS)                += x86/dsputilenc_mmx.o          \
                                            x86/motion_est.o
+ OBJS-$(CONFIG_FDCTDSP)                 += x86/fdctdsp_init.o
  OBJS-$(CONFIG_FFT)                     += x86/fft_init.o
 +OBJS-$(CONFIG_FLAC_DECODER)            += x86/flacdsp_init.o
 +OBJS-$(CONFIG_FLAC_ENCODER)            += x86/flacdsp_init.o
  OBJS-$(CONFIG_H263DSP)                 += x86/h263dsp_init.o
  OBJS-$(CONFIG_H264CHROMA)              += x86/h264chroma_init.o
  OBJS-$(CONFIG_H264DSP)                 += x86/h264dsp_init.o
@@@ -56,10 -50,11 +57,10 @@@ OBJS-$(CONFIG_VP6_DECODER)             
  OBJS-$(CONFIG_VP7_DECODER)             += x86/vp8dsp_init.o
  OBJS-$(CONFIG_VP8_DECODER)             += x86/vp8dsp_init.o
  OBJS-$(CONFIG_VP9_DECODER)             += x86/vp9dsp_init.o
 +OBJS-$(CONFIG_WEBP_DECODER)            += x86/vp8dsp_init.o
  
 -MMX-OBJS-$(CONFIG_AUDIODSP)            += x86/audiodsp_mmx.o
 -MMX-OBJS-$(CONFIG_HPELDSP)             += x86/fpel_mmx.o                \
 -                                          x86/hpeldsp_mmx.o
 +MMX-OBJS-$(CONFIG_DIRAC_DECODER)       += x86/dirac_dwt.o
- MMX-OBJS-$(CONFIG_ENCODERS)            += x86/fdct.o
+ MMX-OBJS-$(CONFIG_FDCTDSP)             += x86/fdct.o
  MMX-OBJS-$(CONFIG_IDCTDSP)             += x86/idctdsp_mmx.o             \
                                            x86/idct_mmx_xvid.o           \
                                            x86/idct_sse2_xvid.o          \
@@@ -367,22 -835,21 +365,14 @@@ av_cold void ff_dsputilenc_init_mmx(DSP
  
  #if HAVE_INLINE_ASM
      if (INLINE_MMX(cpu_flags)) {
-         if (!high_bit_depth &&
-             (dct_algo == FF_DCT_AUTO || dct_algo == FF_DCT_MMX))
-             c->fdct = ff_fdct_mmx;
 -        c->sum_abs_dctelem = sum_abs_dctelem_mmx;
--
 -        c->sse[0]  = sse16_mmx;
 -        c->sse[1]  = sse8_mmx;
          c->vsad[4] = vsad_intra16_mmx;
  
 -        c->nsse[0] = nsse16_mmx;
 -        c->nsse[1] = nsse8_mmx;
          if (!(avctx->flags & CODEC_FLAG_BITEXACT)) {
              c->vsad[0]      = vsad16_mmx;
          }
      }
  
      if (INLINE_MMXEXT(cpu_flags)) {
-         if (!high_bit_depth &&
-             (dct_algo == FF_DCT_AUTO || dct_algo == FF_DCT_MMX))
-             c->fdct = ff_fdct_mmxext;
 -        c->sum_abs_dctelem = sum_abs_dctelem_mmxext;
          c->vsad[4]         = vsad_intra16_mmxext;
  
          if (!(avctx->flags & CODEC_FLAG_BITEXACT)) {
      }
  
      if (INLINE_SSE2(cpu_flags)) {
-         if (!high_bit_depth &&
-             (dct_algo == FF_DCT_AUTO || dct_algo == FF_DCT_MMX))
-             c->fdct = ff_fdct_sse2;
 -        c->sum_abs_dctelem = sum_abs_dctelem_sse2;
      }
  
  #if HAVE_SSSE3_INLINE
index 0000000,93fdd65..261db97
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,44 +1,44 @@@
 - * This file is part of Libav.
+ /*
 - * Libav is free software; you can redistribute it and/or
++ * This file is part of FFmpeg.
+  *
 - * Libav is distributed in the hope that it will be useful,
++ * FFmpeg is free software; you can redistribute it and/or
+  * modify it under the terms of the GNU Lesser General Public
+  * License as published by the Free Software Foundation; either
+  * version 2.1 of the License, or (at your option) any later version.
+  *
 - * License along with Libav; if not, write to the Free Software
++ * FFmpeg is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  * Lesser General Public License for more details.
+  *
+  * You should have received a copy of the GNU Lesser General Public
++ * License along with FFmpeg; if not, write to the Free Software
+  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+  */
+ #include "libavutil/attributes.h"
+ #include "libavutil/cpu.h"
+ #include "libavutil/x86/cpu.h"
+ #include "libavcodec/avcodec.h"
+ #include "libavcodec/dct.h"
+ #include "libavcodec/fdctdsp.h"
+ av_cold void ff_fdctdsp_init_x86(FDCTDSPContext *c, AVCodecContext *avctx,
+                                  unsigned high_bit_depth)
+ {
+     int cpu_flags = av_get_cpu_flags();
+     const int dct_algo = avctx->dct_algo;
+     if (!high_bit_depth) {
+         if ((dct_algo == FF_DCT_AUTO || dct_algo == FF_DCT_MMX)) {
+             if (INLINE_MMX(cpu_flags))
+                 c->fdct = ff_fdct_mmx;
+             if (INLINE_MMXEXT(cpu_flags))
+                 c->fdct = ff_fdct_mmxext;
+             if (INLINE_SSE2(cpu_flags))
+                 c->fdct = ff_fdct_sse2;
+         }
+     }
+ }
index 5c4ebdc,0000000..9df87ff
mode 100644,000000..100644
--- /dev/null
@@@ -1,438 -1,0 +1,439 @@@
-                 p->dsp.fdct(block);
 +/*
 + * Copyright (c) 2003 Michael Niedermayer <michaelni@gmx.at>
 + * Copyright (c) 2013 Clément Bœsch <u pkh me>
 + *
 + * This file is part of FFmpeg.
 + *
 + * FFmpeg 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.
 + *
 + * 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 General Public License for more details.
 + *
 + * You should have received a copy of the GNU 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
 + * Simple post processing filter
 + *
 + * This implementation is based on an algorithm described in
 + * "Aria Nosratinia Embedded Post-Processing for
 + * Enhancement of Compressed Images (1999)"
 + *
 + * Originally written by Michael Niedermayer for the MPlayer project, and
 + * ported by Clément Bœsch for FFmpeg.
 + */
 +
 +#include "libavcodec/dsputil.h"
 +#include "libavutil/avassert.h"
 +#include "libavutil/imgutils.h"
 +#include "libavutil/opt.h"
 +#include "libavutil/pixdesc.h"
 +#include "internal.h"
 +#include "vf_spp.h"
 +
 +enum mode {
 +    MODE_HARD,
 +    MODE_SOFT,
 +    NB_MODES
 +};
 +
 +#define OFFSET(x) offsetof(SPPContext, x)
 +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
 +static const AVOption spp_options[] = {
 +    { "quality", "set quality", OFFSET(log2_count), AV_OPT_TYPE_INT, {.i64 = 3}, 0, MAX_LEVEL, FLAGS },
 +    { "qp", "force a constant quantizer parameter", OFFSET(qp), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 63, FLAGS },
 +    { "mode", "set thresholding mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64 = MODE_HARD}, 0, NB_MODES - 1, FLAGS, "mode" },
 +        { "hard", "hard thresholding", 0, AV_OPT_TYPE_CONST, {.i64 = MODE_HARD}, INT_MIN, INT_MAX, FLAGS, "mode" },
 +        { "soft", "soft thresholding", 0, AV_OPT_TYPE_CONST, {.i64 = MODE_SOFT}, INT_MIN, INT_MAX, FLAGS, "mode" },
 +    { "use_bframe_qp", "use B-frames' QP", OFFSET(use_bframe_qp), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, FLAGS },
 +    { NULL }
 +};
 +
 +AVFILTER_DEFINE_CLASS(spp);
 +
 +// XXX: share between filters?
 +DECLARE_ALIGNED(8, static const uint8_t, ldither)[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 },
 +};
 +
 +static const uint8_t offset[127][2] = {
 +    {0,0},
 +    {0,0}, {4,4},                                           // quality = 1
 +    {0,0}, {2,2}, {6,4}, {4,6},                             // quality = 2
 +    {0,0}, {5,1}, {2,2}, {7,3}, {4,4}, {1,5}, {6,6}, {3,7}, // quality = 3
 +
 +    {0,0}, {4,0}, {1,1}, {5,1}, {3,2}, {7,2}, {2,3}, {6,3}, // quality = 4
 +    {0,4}, {4,4}, {1,5}, {5,5}, {3,6}, {7,6}, {2,7}, {6,7},
 +
 +    {0,0}, {0,2}, {0,4}, {0,6}, {1,1}, {1,3}, {1,5}, {1,7}, // quality = 5
 +    {2,0}, {2,2}, {2,4}, {2,6}, {3,1}, {3,3}, {3,5}, {3,7},
 +    {4,0}, {4,2}, {4,4}, {4,6}, {5,1}, {5,3}, {5,5}, {5,7},
 +    {6,0}, {6,2}, {6,4}, {6,6}, {7,1}, {7,3}, {7,5}, {7,7},
 +
 +    {0,0}, {4,4}, {0,4}, {4,0}, {2,2}, {6,6}, {2,6}, {6,2}, // quality = 6
 +    {0,2}, {4,6}, {0,6}, {4,2}, {2,0}, {6,4}, {2,4}, {6,0},
 +    {1,1}, {5,5}, {1,5}, {5,1}, {3,3}, {7,7}, {3,7}, {7,3},
 +    {1,3}, {5,7}, {1,7}, {5,3}, {3,1}, {7,5}, {3,5}, {7,1},
 +    {0,1}, {4,5}, {0,5}, {4,1}, {2,3}, {6,7}, {2,7}, {6,3},
 +    {0,3}, {4,7}, {0,7}, {4,3}, {2,1}, {6,5}, {2,5}, {6,1},
 +    {1,0}, {5,4}, {1,4}, {5,0}, {3,2}, {7,6}, {3,6}, {7,2},
 +    {1,2}, {5,6}, {1,6}, {5,2}, {3,0}, {7,4}, {3,4}, {7,0},
 +};
 +
 +static void hardthresh_c(int16_t dst[64], const int16_t src[64],
 +                         int qp, const uint8_t *permutation)
 +{
 +    int i;
 +    int bias = 0; // FIXME
 +
 +    unsigned threshold1 = qp * ((1<<4) - bias) - 1;
 +    unsigned threshold2 = threshold1 << 1;
 +
 +    memset(dst, 0, 64 * sizeof(dst[0]));
 +    dst[0] = (src[0] + 4) >> 3;
 +
 +    for (i = 1; i < 64; i++) {
 +        int level = src[i];
 +        if (((unsigned)(level + threshold1)) > threshold2) {
 +            const int j = permutation[i];
 +            dst[j] = (level + 4) >> 3;
 +        }
 +    }
 +}
 +
 +static void softthresh_c(int16_t dst[64], const int16_t src[64],
 +                         int qp, const uint8_t *permutation)
 +{
 +    int i;
 +    int bias = 0; //FIXME
 +
 +    unsigned threshold1 = qp * ((1<<4) - bias) - 1;
 +    unsigned threshold2 = threshold1 << 1;
 +
 +    memset(dst, 0, 64 * sizeof(dst[0]));
 +    dst[0] = (src[0] + 4) >> 3;
 +
 +    for (i = 1; i < 64; i++) {
 +        int level = src[i];
 +        if (((unsigned)(level + threshold1)) > threshold2) {
 +            const int j = permutation[i];
 +            if (level > 0) dst[j] = (level - threshold1 + 4) >> 3;
 +            else           dst[j] = (level + threshold1 + 4) >> 3;
 +        }
 +    }
 +}
 +
 +static void store_slice_c(uint8_t *dst, const int16_t *src,
 +                          int dst_linesize, int src_linesize,
 +                          int width, int height, int log2_scale,
 +                          const uint8_t dither[8][8])
 +{
 +    int y, x;
 +
 +#define STORE(pos) do {                                                     \
 +    temp = ((src[x + y*src_linesize + pos] << log2_scale) + d[pos]) >> 6;   \
 +    if (temp & 0x100)                                                       \
 +        temp = ~(temp >> 31);                                               \
 +    dst[x + y*dst_linesize + pos] = temp;                                   \
 +} while (0)
 +
 +    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);
 +        }
 +    }
 +}
 +
 +static inline void add_block(int16_t *dst, int linesize, const int16_t block[64])
 +{
 +    int y;
 +
 +    for (y = 0; y < 8; y++) {
 +        *(uint32_t *)&dst[0 + y*linesize] += *(uint32_t *)&block[0 + y*8];
 +        *(uint32_t *)&dst[2 + y*linesize] += *(uint32_t *)&block[2 + y*8];
 +        *(uint32_t *)&dst[4 + y*linesize] += *(uint32_t *)&block[4 + y*8];
 +        *(uint32_t *)&dst[6 + y*linesize] += *(uint32_t *)&block[6 + y*8];
 +    }
 +}
 +
 +// XXX: export the function?
 +static inline int norm_qscale(int qscale, int type)
 +{
 +    switch (type) {
 +    case FF_QSCALE_TYPE_MPEG1: return qscale;
 +    case FF_QSCALE_TYPE_MPEG2: return qscale >> 1;
 +    case FF_QSCALE_TYPE_H264:  return qscale >> 2;
 +    case FF_QSCALE_TYPE_VP56:  return (63 - qscale + 2) >> 2;
 +    }
 +    return qscale;
 +}
 +
 +static void filter(SPPContext *p, uint8_t *dst, uint8_t *src,
 +                   int dst_linesize, int src_linesize, int width, int height,
 +                   const uint8_t *qp_table, int qp_stride, int is_luma)
 +{
 +    int x, y, i;
 +    const int count = 1 << p->log2_count;
 +    const int linesize = is_luma ? p->temp_linesize : FFALIGN(width+16, 16);
 +    DECLARE_ALIGNED(16, uint64_t, block_align)[32];
 +    int16_t *block  = (int16_t *)block_align;
 +    int16_t *block2 = (int16_t *)(block_align + 16);
 +
 +    for (y = 0; y < height; y++) {
 +        int index = 8 + 8*linesize + y*linesize;
 +        memcpy(p->src + index, src + y*src_linesize, width);
 +        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++) {
 +        memcpy(p->src + (       7-y)*linesize, p->src + (       y+8)*linesize, linesize);
 +        memcpy(p->src + (height+8+y)*linesize, p->src + (height-y+7)*linesize, linesize);
 +    }
 +
 +    for (y = 0; y < height + 8; y += 8) {
 +        memset(p->temp + (8 + y) * linesize, 0, 8 * linesize * sizeof(*p->temp));
 +        for (x = 0; x < width + 8; x += 8) {
 +            int qp;
 +
 +            if (p->qp) {
 +                qp = p->qp;
 +            } else{
 +                const int qps = 3 + is_luma;
 +                qp = qp_table[(FFMIN(x, width - 1) >> qps) + (FFMIN(y, height - 1) >> qps) * qp_stride];
 +                qp = FFMAX(1, norm_qscale(qp, p->qscale_type));
 +            }
 +            for (i = 0; i < count; i++) {
 +                const int x1 = x + offset[i + count - 1][0];
 +                const int y1 = y + offset[i + count - 1][1];
 +                const int index = x1 + y1*linesize;
 +                p->dsp.get_pixels(block, p->src + index, linesize);
++                p->fdsp.fdct(block);
 +                p->requantize(block2, block, qp, p->idsp.idct_permutation);
 +                p->idsp.idct(block2);
 +                add_block(p->temp + index, linesize, block2);
 +            }
 +        }
 +        if (y)
 +            p->store_slice(dst + (y - 8) * dst_linesize, p->temp + 8 + y*linesize,
 +                           dst_linesize, linesize, width,
 +                           FFMIN(8, height + 8 - y), MAX_LEVEL - p->log2_count,
 +                           ldither);
 +    }
 +}
 +
 +static int query_formats(AVFilterContext *ctx)
 +{
 +    static const enum PixelFormat pix_fmts[] = {
 +        AV_PIX_FMT_YUV444P,  AV_PIX_FMT_YUV422P,
 +        AV_PIX_FMT_YUV420P,  AV_PIX_FMT_YUV411P,
 +        AV_PIX_FMT_YUV410P,  AV_PIX_FMT_YUV440P,
 +        AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVJ422P,
 +        AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ440P,
 +        AV_PIX_FMT_NONE
 +    };
 +    ff_set_common_formats(ctx, ff_make_format_list(pix_fmts));
 +    return 0;
 +}
 +
 +static int config_input(AVFilterLink *inlink)
 +{
 +    SPPContext *spp = inlink->dst->priv;
 +    const int h = FFALIGN(inlink->h + 16, 16);
 +    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
 +
 +    spp->hsub = desc->log2_chroma_w;
 +    spp->vsub = desc->log2_chroma_h;
 +    spp->temp_linesize = FFALIGN(inlink->w + 16, 16);
 +    spp->temp = av_malloc_array(spp->temp_linesize, h * sizeof(*spp->temp));
 +    spp->src  = av_malloc_array(spp->temp_linesize, h * sizeof(*spp->src));
 +    if (!spp->use_bframe_qp) {
 +        /* we are assuming here the qp blocks will not be smaller that 16x16 */
 +        spp->non_b_qp_alloc_size = FF_CEIL_RSHIFT(inlink->w, 4) * FF_CEIL_RSHIFT(inlink->h, 4);
 +        spp->non_b_qp_table = av_calloc(spp->non_b_qp_alloc_size, sizeof(*spp->non_b_qp_table));
 +        if (!spp->non_b_qp_table)
 +            return AVERROR(ENOMEM);
 +    }
 +    if (!spp->temp || !spp->src)
 +        return AVERROR(ENOMEM);
 +    return 0;
 +}
 +
 +static int filter_frame(AVFilterLink *inlink, AVFrame *in)
 +{
 +    AVFilterContext *ctx = inlink->dst;
 +    SPPContext *spp = ctx->priv;
 +    AVFilterLink *outlink = ctx->outputs[0];
 +    AVFrame *out = in;
 +    int qp_stride = 0;
 +    const int8_t *qp_table = NULL;
 +
 +    /* if we are not in a constant user quantizer mode and we don't want to use
 +     * the quantizers from the B-frames (B-frames often have a higher QP), we
 +     * need to save the qp table from the last non B-frame; this is what the
 +     * following code block does */
 +    if (!spp->qp) {
 +        qp_table = av_frame_get_qp_table(in, &qp_stride, &spp->qscale_type);
 +
 +        if (qp_table && !spp->use_bframe_qp && in->pict_type != AV_PICTURE_TYPE_B) {
 +            int w, h;
 +
 +            /* if the qp stride is not set, it means the QP are only defined on
 +             * a line basis */
 +            if (!qp_stride) {
 +                w = FF_CEIL_RSHIFT(inlink->w, 4);
 +                h = 1;
 +            } else {
 +                w = FF_CEIL_RSHIFT(qp_stride, 4);
 +                h = FF_CEIL_RSHIFT(inlink->h, 4);
 +            }
 +            av_assert0(w * h <= spp->non_b_qp_alloc_size);
 +            memcpy(spp->non_b_qp_table, qp_table, w * h);
 +        }
 +    }
 +
 +    if (spp->log2_count && !ctx->is_disabled) {
 +        if (!spp->use_bframe_qp && spp->non_b_qp_table)
 +            qp_table = spp->non_b_qp_table;
 +
 +        if (qp_table || spp->qp) {
 +            const int cw = FF_CEIL_RSHIFT(inlink->w, spp->hsub);
 +            const int ch = FF_CEIL_RSHIFT(inlink->h, spp->vsub);
 +
 +            /* get a new frame if in-place is not possible or if the dimensions
 +             * are not multiple of 8 */
 +            if (!av_frame_is_writable(in) || (inlink->w & 7) || (inlink->h & 7)) {
 +                const int aligned_w = FFALIGN(inlink->w, 8);
 +                const int aligned_h = FFALIGN(inlink->h, 8);
 +
 +                out = ff_get_video_buffer(outlink, aligned_w, aligned_h);
 +                if (!out) {
 +                    av_frame_free(&in);
 +                    return AVERROR(ENOMEM);
 +                }
 +                av_frame_copy_props(out, in);
 +                out->width  = in->width;
 +                out->height = in->height;
 +            }
 +
 +            filter(spp, out->data[0], in->data[0], out->linesize[0], in->linesize[0], inlink->w, inlink->h, qp_table, qp_stride, 1);
 +            filter(spp, out->data[1], in->data[1], out->linesize[1], in->linesize[1], cw,        ch,        qp_table, qp_stride, 0);
 +            filter(spp, out->data[2], in->data[2], out->linesize[2], in->linesize[2], cw,        ch,        qp_table, qp_stride, 0);
 +            emms_c();
 +        }
 +    }
 +
 +    if (in != out) {
 +        if (in->data[3])
 +            av_image_copy_plane(out->data[3], out->linesize[3],
 +                                in ->data[3], in ->linesize[3],
 +                                inlink->w, inlink->h);
 +        av_frame_free(&in);
 +    }
 +    return ff_filter_frame(outlink, out);
 +}
 +
 +static int process_command(AVFilterContext *ctx, const char *cmd, const char *args,
 +                           char *res, int res_len, int flags)
 +{
 +    SPPContext *spp = ctx->priv;
 +
 +    if (!strcmp(cmd, "level")) {
 +        if (!strcmp(args, "max"))
 +            spp->log2_count = MAX_LEVEL;
 +        else
 +            spp->log2_count = av_clip(strtol(args, NULL, 10), 0, MAX_LEVEL);
 +        return 0;
 +    }
 +    return AVERROR(ENOSYS);
 +}
 +
 +static av_cold int init(AVFilterContext *ctx)
 +{
 +    SPPContext *spp = ctx->priv;
 +
 +    spp->avctx = avcodec_alloc_context3(NULL);
 +    if (!spp->avctx)
 +        return AVERROR(ENOMEM);
 +    avpriv_dsputil_init(&spp->dsp, spp->avctx);
 +    ff_idctdsp_init(&spp->idsp, spp->avctx);
++    ff_fdctdsp_init(&spp->fdsp, spp->avctx);
 +    spp->store_slice = store_slice_c;
 +    switch (spp->mode) {
 +    case MODE_HARD: spp->requantize = hardthresh_c; break;
 +    case MODE_SOFT: spp->requantize = softthresh_c; break;
 +    }
 +    if (ARCH_X86)
 +        ff_spp_init_x86(spp);
 +    return 0;
 +}
 +
 +static av_cold void uninit(AVFilterContext *ctx)
 +{
 +    SPPContext *spp = ctx->priv;
 +
 +    av_freep(&spp->temp);
 +    av_freep(&spp->src);
 +    if (spp->avctx) {
 +        avcodec_close(spp->avctx);
 +        av_freep(&spp->avctx);
 +    }
 +    av_freep(&spp->non_b_qp_table);
 +}
 +
 +static const AVFilterPad spp_inputs[] = {
 +    {
 +        .name         = "default",
 +        .type         = AVMEDIA_TYPE_VIDEO,
 +        .config_props = config_input,
 +        .filter_frame = filter_frame,
 +    },
 +    { NULL }
 +};
 +
 +static const AVFilterPad spp_outputs[] = {
 +    {
 +        .name = "default",
 +        .type = AVMEDIA_TYPE_VIDEO,
 +    },
 +    { NULL }
 +};
 +
 +AVFilter ff_vf_spp = {
 +    .name            = "spp",
 +    .description     = NULL_IF_CONFIG_SMALL("Apply a simple post processing filter."),
 +    .priv_size       = sizeof(SPPContext),
 +    .init            = init,
 +    .uninit          = uninit,
 +    .query_formats   = query_formats,
 +    .inputs          = spp_inputs,
 +    .outputs         = spp_outputs,
 +    .process_command = process_command,
 +    .priv_class      = &spp_class,
 +    .flags           = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL,
 +};
index 1884745,0000000..909d4de
mode 100644,000000..100644
--- /dev/null
@@@ -1,61 -1,0 +1,63 @@@
 +/*
 + * Copyright (c) 2003 Michael Niedermayer <michaelni@gmx.at>
 + * Copyright (c) 2013 Clément Bœsch
 + *
 + * This file is part of FFmpeg.
 + *
 + * FFmpeg 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.
 + *
 + * 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 General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License along
 + * with FFmpeg; if not, write to the Free Software Foundation, Inc.,
 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 + */
 +
 +#ifndef AVFILTER_SPP_H
 +#define AVFILTER_SPP_H
 +
 +#include "libavcodec/avcodec.h"
 +#include "libavcodec/dsputil.h"
 +#include "libavcodec/idctdsp.h"
++#include "libavcodec/fdctdsp.h"
 +#include "avfilter.h"
 +
 +#define MAX_LEVEL 6 /* quality levels */
 +
 +typedef struct {
 +    const AVClass *av_class;
 +
 +    int log2_count;
 +    int qp;
 +    int mode;
 +    int qscale_type;
 +    int temp_linesize;
 +    uint8_t *src;
 +    int16_t *temp;
 +    AVCodecContext *avctx;
 +    DSPContext dsp;
 +    IDCTDSPContext idsp;
++    FDCTDSPContext fdsp;
 +    int8_t *non_b_qp_table;
 +    int non_b_qp_alloc_size;
 +    int use_bframe_qp;
 +    int hsub, vsub;
 +
 +    void (*store_slice)(uint8_t *dst, const int16_t *src,
 +                        int dst_stride, int src_stride,
 +                        int width, int height, int log2_scale,
 +                        const uint8_t dither[8][8]);
 +
 +    void (*requantize)(int16_t dst[64], const int16_t src[64],
 +                       int qp, const uint8_t *permutation);
 +} SPPContext;
 +
 +void ff_spp_init_x86(SPPContext *s);
 +
 +#endif /* AVFILTER_SPP_H */