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
-         }
      }
  }
Simple merge
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
 +};
Simple merge
@@@ -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 */